# Project export: Pvpark

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: A website designed to help users get out and interact with others through settings up sports games at local parks.
- Devpost: https://devpost.com/software/pvpark
- GitHub: https://github.com/yeaung00/pvpark_api
- Team: 0 GitHub contributor(s) — 

## Devpost submission (written by the team)

### Inspiration

As computer science students, we're well aware of the negative consequences that come with prolonged coding sessions and a sedentary lifestyle. That's why we decided to center our attention on 'HealthHacks,' aiming to enhance overall well-being by promoting physical activity. Our primary goal was to develop an interactive website that motivates individuals to step outdoors, engage in physical movement, and ideally, foster user commitment for long-term benefits.

### What it does

We developed a website that enables users to initiate or join sports matches at their preferred parks. After selecting the park, the website provides real-time weather conditions to help users prepare for the environment. For those seeking a challenging experience, we introduced a ranked option featuring a skill-based matchmaking system. Additionally, users can explore their overall statistics in the profile section, offering insights into their performance across different sports categories.

### How we built it

We first thought about the interface of the website using a flowchart. Then we built the front end using react js and tailwind. Last thing we integrated was the api to help us search for what we needed in our projects.

### Challenges we ran into

The biggest challenge we faced was our unfamiliarity with react and tailwind which is what we decided to use to build our website. Another problem was the time constraint since we were spending half of the time researching the fundamentals we lacked.

### Accomplishments we're proud of

We are proud of the fact that we were able to not only learn react and tailwind which were the main parts of our website, but also we were able to put out a pretty good looking product.

### What we learned

We learned react and tailwind. We also tapped into our creative side and learned more about how to design a website.

### What's next

Some future improvements we have is to implement a login system and for users to fully customize their own profile with stat tracking across multiple sports, a friend system, etc.

## README (from the GitHub repository)

No README available.

## Detected evidence (automated analysis)

Indexed codebase: 10 recognized source files, 7 KB.
- Express (technology) — detected in the code
- JavaScript (language) — detected in the code
- Supabase (technology) — detected in the code
- React (technology) — claimed on Devpost, not found in the code
- Tailwind CSS (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (13 of 13)

```
.gitignore
app.js
controllers/cityRouter.js
controllers/userRouter.js
lib/supabase/city.js
lib/supabase/client.js
lib/supabase/games.js
lib/supabase/parks.js
lib/supabase/user.js
lib/weather.js
lib/yelp.js
package.json
vercel.json
```

### Dependencies

- package.json: @supabase/supabase-js@^2.39.3, cors@^2.8.5, dotenv@^16.3.2, express@^4.18.2, nodemon@^3.0.3, request@^2.88.2, yelp-fusion@^3.0.0

### Recent commits (newest first)

- cors
- fixed
- fixed
- fixed
- db changes
- crazy
- adsf
- cors fix
- added cors origin
- second
- redirect
- first commit

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

### package.json

```
{
  "name": "pvpark_api",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "directories": {
    "lib": "lib"
  },
  "scripts": {
    "dev": "nodemon app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@supabase/supabase-js": "^2.39.3",
    "cors": "^2.8.5",
    "dotenv": "^16.3.2",
    "express": "^4.18.2",
    "nodemon": "^3.0.3",
    "request": "^2.88.2",
    "yelp-fusion": "^3.0.0"
  }
}

```

### app.js

```javascript
const express = require('express');
const app = express();
const cors = require('cors');
require('dotenv').config();
const cityRouter = require('./controllers/cityRouter');
const userRouter = require('./controllers/userRouter');
app.use(express.json());
// app.use(express.urlencoded({ extended: true }));
const corsOptions = cors({
    origin: ['http://localhost:5173', 'http://127.0.0.1:5173', 'https://pvpark-frontend.vercel.app/'],
    methods: '*',
    allowedHeaders: ['Content-Type', 'Authorization'],
    credentials: true,
  })
;
app.use(corsOptions);

app.get('/', (_, res) => res.redirect('/api'));
app.use('/api', cityRouter)
app.use('/api/users', userRouter)

app.listen(3001, () => console.log('listening on port http://localhost:3001'))

module.exports = app;
```

### controllers/userRouter.js

```javascript
const { signIn } = require('../lib/supabase/user')

const userRouter = require('express').Router()

userRouter.get('/signin', async (req, res) => {
  signIn()
})

module.exports = userRouter
```

### lib/weather.js

```javascript
async function getWeather(city, state) {
  const url = process.env.WEATHER_API_URL
  const weatherApiKey = process.env.WEATHER_API_KEY

  const response = await fetch(`${url}q=${city},${state},US&units=imperial&appid=${weatherApiKey}`)
  let data = await response.json()
  const sunrise = new Date(data.sys.sunrise * 1000)
    .toLocaleTimeString()
    .split(':')
    .slice(0, 2)
    .join(':')
  const sunset = new Date(data.sys.sunset * 1000).toLocaleTimeString()
    .split(':')
    .slice(0, 2)
    .join(':')
  data = {
    icon_id: data.weather[0].icon,
    description: data.weather[0].main,
    temp: Math.round(data.main.temp),
    wind_speed: data.wind.speed,
    sunrise: sunrise + ' AM',
    sunset: sunset + ' PM',
  }
  return data
}


module.exports = { getWeather }
```

### lib/yelp.js

```javascript
function filterCategories(categories) {
  const hasSports = (category) => category == 'football' || category == 'basketballcourts' || category == 'baseballfields'
  categories = categories.filter(category => hasSports(category.alias))
  const aliasMap = {
    'basketballcourts': 'Basketball',
    'football': 'Soccer',
    'baseballfields': 'Baseball'
  }
  return categories.map(category => aliasMap[category.alias])
}
async function getParks(city, state) {
  const url = process.env.YELP_API_URL
  const headers = {
    'Authorization': `Bearer ${process.env.YELP_API_KEY}`,
    'Content-Type': 'application/json',
  }
  let data;
  try {
    const response = await fetch(`${url}sort_by=best_match&term=parks&categories=basketballcourts,baseballfields,football&location=${city}, ${state}&limit=20`, { headers })
    data = (await response.json()).businesses
  } catch (error) {
    throw(error)
  }
  data = data.map(({name, image_url, location, categories, id }) => {
    categories = filterCategories(categories)
    return ({
      id,
      name, 
      categories,
      image_url, 
      address: location.address1, 
      city: location.city,
      state: location.state,
      player_count: 0,
      near_by: `${city},${state}`,
    })
  })

  return data
}

module.exports = { getParks }
```

### controllers/cityRouter.js

```javascript
const cityRouter = require('express').Router()
const { getParks } = require('../lib/yelp.js')
const { getWeather } = require('../lib/weather.js')
const {  getGamesFromDB, postGameToDB,  } = require('../lib/supabase/games.js')
const { getParksFromDB, getParkFromDB, postParksToDB, updatePark } = require('../lib/supabase/parks.js')
const { postCityToDB } = require('../lib/supabase/city.js')

cityRouter.get('/', (req, res) => {
  res.send('Hello')
})

cityRouter.get('/:state/:city/parks', async (req, res) => {
  const state = req.params.state, city = req.params.city
  let parks = await getParks(city, state)
  res.json(parks)
});

cityRouter.get('/:state/:city/weather', async (req, res) => {
  const state = req.params.state, city = req.params.city
  const weather = await getWeather(city, state)
  res.json(weather)
});

cityRouter.post('/parks/:parkId/games', async (req, res) => {
  const { name, gameType, maxPlayers } = req.body
  const parkId = req.params.parkId
  const game = {
    park_id: parkId,
    name,
    game_type: gameType[0].toUpperCase() + gameType.slice(1),
    max_players: maxPlayers,
    player_count: 1
  }
  const games = await getGamesFromDB(parkId)
  const playerCounts = games.map(game => game.player_count)
  const totalPlayers = playerCounts.reduce((total, count) => total + count, 0)
  let park = await getParkFromDB(parkId)
  park = {...park, player_count: totalPlayers}
  await postGameToDB(parkId, game)
  await updatePark(park, parkId)
  res.send(`Game: ${name} posted in park: ${parkId}`).status(200)
});

module.exports = cityRouter;
```

### lib/supabase/user.js

```javascript
const { supabase } = require('./client.js')

async function signIn() {
  const { data, error } = await supabase.auth.signInWithOAuth({
    provider: 'google'
  })
}

module.exports = {
  signIn,
}

```

### lib/supabase/client.js

```javascript
const { createClient } = require('@supabase/supabase-js');
const url = process.env.SUPABASE_API_URL
const supabaseApiKey = process.env.SUPABASE_API_KEY
const supabase = createClient(url, supabaseApiKey)

module.exports = { supabase }
```

### lib/supabase/city.js

```javascript
const { supabase } = require('./client.js')

async function postCityToDB(city, state) {
  try {
    await supabase
      .from('cities')
      .insert({ state, name: city })
  } catch (error) {
    throw(error)
  }
}

module.exports = {
  postCityToDB
}
```

### lib/supabase/games.js

```javascript
const { supabase } = require('./client.js')

async function getGamesFromDB(parkId) {
  const { data, error } = await supabase
    .from('games')
    .select()
    .eq('park_id', parkId)
  if (error) {
    throw(error)
  }
  return data
}
async function postGameToDB(parkId, game) {
  try {
    const { error } = await supabase
      .from('games')
      .insert(game)
  } catch (error){
    throw(error)
  }
}

module.exports = {
  getGamesFromDB,
  postGameToDB,
}
```

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