# Project export: EduCycler

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: Cal Hacks 10.0
- Tagline: EduCycler, where textbooks find new beginnings! Our product lets students sell used college textbooks to incoming peers. Save, earn, and make the academic journey affordable.
- Devpost: https://devpost.com/software/educycler
- GitHub: https://github.com/harshitabha/EduCycle
- Demo: https://www.figma.com/file/ZHIB8mrBKncP55RL9i86qy/EduCycler?type=design&node-id=0%3A1&mode=design&t=6onSHsMgLkdUDVoV-1
- Team: 2 GitHub contributor(s) — Harshita Bhardwaj (5 commits), sharma-pari (1 commits)

## Devpost submission (written by the team)

### Inspiration

The inspiration for creating EduCycler stemmed from an understanding of the financial challenges faced by university students. Textbooks are expensive and often unused after the semester, forever lying in some corner of a room. EduCycler was born out of a desire to empower students to alleviate this financial strain, facilitating a platform where they could easily buy and sell textbooks within their academic community.

### What it does

Our website provides an easy platform for students to sell and buy used textbooks. By allowing users to filter listings by university and course, EduCycler aims to make textbook trading a more efficient, affordable, and environmentally sustainable experience for college students.

### How we built it

EduCycler was created using React. We initially designed the whole website in Figma. This allowed us to optimize our website style, functionality, and layout. We then spent time creating our design in Figma. Throughout this process, GitHub was used for version control.

### Challenges we ran into

As beginners to React, we had a significant challenge in learning how to use the framework. We spent extra hours on tutorials, documentation, and practical exercises. We sought help from mentors, learned collaboratively, and persisted when hitting bugs. We had also planned to use Convex for our backend development. However, we lost a team member partway through the hackathon and had to reevaluate our plan. We overcame this by focusing on creating a working front-end site and implementing features modularly to ensure we had a working product at the end of the hackathon.

### Accomplishments we're proud of

One accomplishment we are proud of is our quick turnaround time when we realized our project would be able to be implemented as we originally intended. Our remaining team members efficiently communicated and got to work.

### What we learned

Through this dedication and commitment to learning, we successfully developed EduCycler, gaining valuable experience in React development along the way.

### What's next

We hope to continue working on this project after the hackathon. We intend to implement a backend database that allows users to create accounts and manage their listings and purchases. Adding an in-built payment system and seller-buyer chat are other primary goals we have. These would allow our website to cover the full textbook resale process, from adding lists to successfully purchasing and picking up the textbooks.

## README (from the GitHub repository)

# EduCycle

A solution for college students to easily purchase textbooks for their classes second-hand from students who have already taken the class. 

Note: Currently the Github pages link does not seem to deploy the web app properly.


## Detected evidence (automated analysis)

Indexed codebase: 19 recognized source files, 18 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- React (technology) — detected in the code

## Codebase structure (from repository index)

### Files (22 of 22)

```
.eslintrc.cjs
.gitignore
index.html
package.json
README.md
src/App.css
src/App.jsx
src/components/Checkboxes.jsx
src/components/Listing.css
src/components/Listing.jsx
src/components/Navbar.css
src/components/Navbar.jsx
src/components/TextInput.jsx
src/index.css
src/main.jsx
src/pages/filters.js
src/pages/form.css
src/pages/Home.css
src/pages/Home.jsx
src/pages/NewListing.css
src/pages/NewListing.jsx
vite.config.js
```

### Dependencies

- package.json: @types/react@^18.2.15, @types/react-dom@^18.2.7, @vitejs/plugin-react@^4.0.3, eslint@^8.45.0, eslint-plugin-react@^7.32.2, eslint-plugin-react-hooks@^4.6.0, eslint-plugin-react-refresh@^0.4.3, react@^18.2.0, react-dom@^18.2.0, react-router-dom@^6.17.0, vite@^4.4.5

### Recent commits (newest first)

- Update README.md
- Merge pull request #1 from harshitabha/home-pg
- We can add cards now!
- Some things show up!
- Working with state is weird
- MEEEEEEEEEEEEEEEEERGE
- Updated input ids
- new home
- Length is a property not a function in js
- Needed to check length
- Created basic shell for state
- Setting up submit button state updating
- Finished adding filter + created component for listing
- Merge pull request #6 from sravangorati2001/home-pg
- Added checkboxes
- Merge pull request #5 from sravangorati2001/home-pg
- Fixed routing
- Finished most styling for add listing page
- Added css for form
- Created very basic new listing form

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

### package.json

```
{
  "name": "edu-cycle",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.17.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.15",
    "@types/react-dom": "^18.2.7",
    "@vitejs/plugin-react": "^4.0.3",
    "eslint": "^8.45.0",
    "eslint-plugin-react": "^7.32.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.3",
    "vite": "^4.4.5"
  }
}

```

### src/main.jsx

```javascript
import React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import App from './App.jsx'

import './index.css'


ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
)

```

### src/App.jsx

```javascript
import { Routes, Route, useNavigate } from 'react-router-dom';

// Pages
import Home from './pages/Home';
import NewListing from './pages/NewListing';
import Navbar from './components/Navbar';


import './App.css';
import { useState } from 'react';

function App() {
  const navigator = useNavigate();

  const [listing, setListing] = useState([]);
  const [newListing, setNewListing] = useState({
    bookName: '',
    isbn: '',
    subject: '',
    condition: '',
    course: '',
    price: '',
    imgSrc: '',
    description: '',
  });
  console.log(listing);

  const handleFormChange = (e) => {
    // update the current listing
    setNewListing((currLisiting) => ({
      ...currLisiting,
      [e.target.name]: [e.target.value]
    }));
  }

  const handleSubmit = () => {
    // update the list of all listings
    setListing((prevListings) => ([
      ...prevListings,
      newListing
    ]))

    // reset the new listing
    setNewListing((curr) => ({
      ...curr,
      bookName: '',
      isbn: '',
      subject: '',
      condition: '',
      course: '',
      price: '',
      imgSrc: '',
      description: '',
    }));

    // go to home
    navigator("/home");
  }

  return (
    <>
      {/* Add the page components here as created */}
        <Navbar  />
        <Routes>
          <Route path="/" element={<Home cards={listing}/>} />
          <Route path="/home" element={<Home cards={listing}/> } />
          {/* Temp Routes*/}
          <Route path="/newListing" element={<NewListing 
                                              handleChange={handleFormChange}
                                              handleSubmit={handleSubmit}/>} />
        </Routes>
    </>
  );
}

export default App

```

### vite.config.js

```javascript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
})

```

### index.html

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="./public/logo.png" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>

```

### src/App.css

```css
#root {
  display: flex;
  flex-direction: column;
  text-align: center;
  width: 100vw;
  height: 100%;
  color: black;
  font-family: Inter;
}

```

### src/index.css

```css
:root {
  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
  line-height: 1.5;
  font-weight: 400;

  color-scheme: light dark;
  color: rgba(255, 255, 255, 0.87);
  background-color: #242424;

  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
}

a {
  font-weight: 500;
  color: #646cff;
  text-decoration: inherit;
}
a:hover {
  color: #535bf2;
}

body {
  margin: 0;
  display: flex;
  /* place-items: center; */
  min-width: 320px;
  min-height: 100vh;
  background-color: #FFFFFF;
}

h1 {
  font-size: 3.2em;
  line-height: 1.1;
}

button {
  border-radius: 8px;
  border: 1px solid transparent;
  padding: 0.6em 1.2em;
  font-size: 1em;
  font-weight: 500;
  font-family: inherit;
  background-color: #1a1a1a;
  cursor: pointer;
  transition: border-color 0.25s;
}
button:hover {
  border-color: #646cff;
}
button:focus,
button:focus-visible {
  outline: 4px auto -webkit-focus-ring-color;
}

@media (prefers-color-scheme: light) {
  :root {
    color: #213547;
    background-color: #ffffff;
  }
  a:hover {
    color: #747bff;
  }
  button {
    background-color: #f9f9f9;
  }
}

```

### src/components/Listing.css

```css
.listing-card {
    width: 400px;
    height: 200px;
    box-shadow: 0px 4px 6px 0px rgba(0, 0, 0, 0.25);
    border-radius: 15px;
    display: flex;
    cursor: pointer;
    background-color: #FFFBED;
}

.card-img {
    border-radius: 15px 0 0 15px;
}

.card-info {
    padding: 10px;
    text-align: start;
}
```

### src/pages/form.css

```css
.form-div {
    display: flex;
    flex-direction: column;
    width: fit-content;
}

.form-lable {
    align-self: start;
}

.form-text {
    color: black !important;
    font-family: Inter;
    font-size: 20px;
    padding: 10px;
}

.form-input {
    box-shadow: 0px 4px 6px 0px rgba(0, 0, 0, 0.25);
    border-radius: 10px;
    width: 35vw;
    background-color: #D9D9D9;
    border: none;
}
```

### src/components/Navbar.css

```css
.nav-bar {
    display: flex;
    justify-content: space-between;
    background-color: #FFF8E1;
    /* width: 100vw; */
    align-items: center;
    padding: 0 10px;
    box-shadow: 0px 4px 6px 0px rgba(0, 0, 0, 0.25);
}

.nav-logo {
    width: 90px;
}

.name-container {
    display: flex;
    align-items: center;
}

.profile-pic {
    height: 65px;
    background-color: white;
    border-radius: 50%;
}

.title {
    color: #774307;
    font-family: Inter;
    font-size: 30px;
    font-style: normal;
    font-weight: 500;
    line-height: normal;
}
```

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