# Project export: SlugWaste

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: CruzHacks 2024
- Tagline: Reducing dining hall waste the slug way!
- Devpost: https://devpost.com/software/slug-waste
- GitHub: https://github.com/violeteloiv/Slug-Waste
- Team: 4 GitHub contributor(s) — Sneha (19 commits), violeteloiv (10 commits), ameeracarat (3 commits), Kavya Ravi (1 commits)

## Devpost submission (written by the team)

### Inspiration

Ever thrown out some food at the dining hall? Ever regretted it? SlugWaste is a project aimed to bring awareness to food waste in UC Santa Cruz's dining halls by self-reporting which meals go to waste the most. Our goal is to give insight into which meals can be improved upon for student satisfaction, along with providing tangible statistics on this matter.

### What it does

SlugWaste is designed to track food waste through self-reporting and give insight into which meals garner the most waste.

### How we built it

SlugWaste comprises of a React+Typescript frontend with a Python+Flask backend connected to an SQLite database.

### Challenges we ran into

For most of us, SlugWaste was our first experience with developing a full-stack product!

### Accomplishments we're proud of

Our SlugWaste logo :)

### What we learned

React + SQLAlchemy + Violet: "how to make a logo"

### What's next

More features + UI design (and actual data from the dining hall?)

## README (from the GitHub repository)

# SlugWaste

**SlugWaste** is a project to bring awareness to food waste in UC Santa Cruz's dining halls by self-reporting which meals go to waste the most. 

Our goal is to give insight into which meals can be improved upon for student satisfaction, along with providing tangible statistics on this matter.

## See our [DevPost][devpost-link]!

Made with :heart: at CruzHacks 2024.

[devpost-link]: https://devpost.com/software/slug-waste


## Detected evidence (automated analysis)

Indexed codebase: 17 recognized source files, 13 KB.
- CSS (language) — detected in the code
- Flask (technology) — detected in the code
- HTML (language) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- TypeScript (language) — detected in the code

## Codebase structure (from repository index)

### Files (23 of 23)

```
.gitignore
CITATIONS.md
package.json
public/index.html
public/manifest.json
public/robots.txt
README.md
requirements.txt
server/app.py
server/tables.py
src/index.css
src/index.tsx
src/Navigation.css
src/Navigation.tsx
src/pages/Login.css
src/pages/LogIn.tsx
src/pages/Submission.tsx
src/react-app-env.d.ts
src/reportWebVitals.ts
src/setupTests.ts
src/SlugWaste.css
src/SlugWaste.tsx
tsconfig.json
```

### Dependencies

- package.json: @testing-library/jest-dom@^5.17.0, @testing-library/react@^13.4.0, @testing-library/user-event@^13.5.0, @types/jest@^27.5.2, @types/node@^16.18.73, @types/react@^18.2.48, @types/react-dom@^18.2.18, react@^18.2.0, react-dom@^18.2.0, react-router-dom@^6.21.3, react-scripts@5.0.1, typescript@^4.9.5, web-vitals@^2.1.4
- requirements.txt: Flask@>=2.1.0, Flask-SQLAlchemy@>=3.0.0

### Recent commits (newest first)

- move dummy_data()
- Merge branch 'main' of https://github.com/violeteloiv/Slug-Waste
- Implemented Navigation Bar
- database shenanigans: the rapture
- Merge branch 'main' into database
- layman's attempt at preventing injection
- finally fixed usermeals
- Login Page Finished
- only load the meals once
- adding dummy data
- Merge branch 'main' of https://github.com/violeteloiv/Slug-Waste
- Basic Home Page
- num bins + more default data
- silly patchups
- Merge branch 'database' of github.com:violeteloiv/Slug-Waste into database
- dummy data time
- database shenanigans: the beginning
- Merge branch 'main' into database
- Merge pull request #4 from violeteloiv/server
- Merge branch 'main' into server

## Key source files (fetched from GitHub, selected and truncated for size)

### CITATIONS.md

```markdown
# Citations

## Documentation used
* Flask
* [Flask-SQLAlchemy](https://flask-sqlalchemy.palletsprojects.com/en/3.1.x/)
* SQLAlchemy

## Non-documenation used
1. [Beginners guide to setting up and running Flask web server](https://dev.to/pratap2210/beginners-guide-to-setting-up-and-running-flask-web-server-1710)
2. ["How to connect a database to a Flask app](https://python-adv-web-apps.readthedocs.io/en/latest/flask_db1.html)
3. [Quick start on Flask-SQLAlchemy](https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/quickstart/)


```

### requirements.txt

```
Flask>=2.1.0
Flask-SQLAlchemy>=3.0.0

```

### package.json

```
{
  "name": "slug-waste",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "@types/jest": "^27.5.2",
    "@types/node": "^16.18.73",
    "@types/react": "^18.2.48",
    "@types/react-dom": "^18.2.18",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.21.3",
    "react-scripts": "5.0.1",
    "typescript": "^4.9.5",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

```

### src/index.tsx

```typescript
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import SlugWaste from './SlugWaste';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);

root.render(
  <React.StrictMode>
    <SlugWaste />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

```

### server/app.py

```python
from flask import Flask, render_template, jsonify, request, redirect, send_from_directory
from sqlalchemy.sql import text

import os

# Import table definitions + SQLAlchemy instance
from tables import *


app = Flask(
 __name__,
 template_folder="../build/",
 static_folder="../build/static",
)

# Standard messages
error_header = "<h1>something went wrong :(\n"
error_text = "<p>Please try again!</p>"


# Creating a database file if it does not exist
db_name = 'database.db'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + db_name
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db.init_app(app)

# Test if database connection is working
def test_database():
    try:
        db.session.query(text("1")).from_statement(text("SELECT 1")).all()
        return True
    except Exception as e:
        return False

@app.route("/")
def login():
    if not test_database():
        return error_header + error_text

    # One-time create all tables (internally will not duplicate)
    with app.app_context():
        db.create_all()
    initalize_dim_tables()

    return render_template('index.html')

# POST from login
@app.route("/login", methods=["POST"])
def handle_login():
    if request.method == "POST":
        try_username = request.form["username"]
        try_password = request.form["password"]

        # these keywords need a space after them so we know it's not part of an actual password
        bad_sqls = ["drop ", "delete ", "update ", "create ", "truncate ", "insert ", "select "]
        lower_pass = try_password.lower()
        for injection in bad_sqls:
            if injection in lower_pass:
                return "<h1>sql injection is a no no! >:(</h1>"

        user = Users.query.filter_by(username=try_username).first()
        if user is not None and len(try_password):
            if len(try_password) and not user.password == try_password:
                return error_header + error_text
            else:
                dummy_data()
                return redirect("/submission")
        else:
            # user did not exist, should lead to a registration page>
            return "<h1>pls register:))</h1>"
    
    return "<h1>invalid login</h1>"

# redundancies to push back to react router for redirects
@app.route('/sub-path',  defaults={'path': 'index.html'})
@app.route('/sub-path/<path:path>')
def index(path):
    return send_from_directory('../build', path)

@app.errorhandler(404)
def not_found(e):
  return send_from_directory('../build','index.html')

if __name__ == "__main__":
    app.run(port=8000, debug=True)
```

### src/react-app-env.d.ts

```typescript
/// <reference types="react-scripts" />

```

### src/SlugWaste.css

```css
body {
  background-size: cover;
  background-color: rgb(150, 150, 150);
  justify-content: center;
}
```

### src/setupTests.ts

```typescript
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

```

### src/index.css

```css
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}

```

### src/reportWebVitals.ts

```typescript
import { ReportHandler } from 'web-vitals';

const reportWebVitals = (onPerfEntry?: ReportHandler) => {
  if (onPerfEntry && onPerfEntry instanceof Function) {
    import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
      getCLS(onPerfEntry);
      getFID(onPerfEntry);
      getFCP(onPerfEntry);
      getLCP(onPerfEntry);
      getTTFB(onPerfEntry);
    });
  }
};

export default reportWebVitals;

```

[8 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]