Skip to content

Commit

Permalink
0. Project Setup
Browse files Browse the repository at this point in the history
  • Loading branch information
sofiane-abou-abderrahim committed May 29, 2024
0 parents commit 1a413f3
Show file tree
Hide file tree
Showing 37 changed files with 6,450 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react/jsx-runtime',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
settings: { react: { version: '18.2' } },
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
'react/prop-types': 'off',
},
}
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Data Fetching With Tanstack Query (formerly React Query)

## Sending HTTP Requests With Ease

- What Is Tanstack Query & Why Would You Use It?
- Fetching & Mutating Data
- Configuring Tanstack Query
- Advanced Concepts: Cache Invalidation, Optimistic Updating & More

# React + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

# Steps

## 0. Project Setup

2. in your terminal, run `cd backend` & `npm install` & `npm start`
1. open a new terminal & run `npm install` & `npm run dev`
175 changes: 175 additions & 0 deletions backend/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import fs from 'node:fs/promises';

import bodyParser from 'body-parser';
import express from 'express';

const app = express();

app.use(bodyParser.json());
app.use(express.static('public'));

app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader(
'Access-Control-Allow-Methods',
'GET, POST, PUT, DELETE, OPTIONS'
);
res.setHeader(
'Access-Control-Allow-Headers',
'X-Requested-With,content-type'
);
next();
});

app.get('/events', async (req, res) => {
const { max, search } = req.query;
const eventsFileContent = await fs.readFile('./data/events.json');
let events = JSON.parse(eventsFileContent);

if (search) {
events = events.filter((event) => {
const searchableText = `${event.title} ${event.description} ${event.location}`;
return searchableText.toLowerCase().includes(search.toLowerCase());
});
}

if (max) {
events = events.slice(events.length - max, events.length);
}

res.json({
events: events.map((event) => ({
id: event.id,
title: event.title,
image: event.image,
date: event.date,
location: event.location,
})),
});
});

app.get('/events/images', async (req, res) => {
const imagesFileContent = await fs.readFile('./data/images.json');
const images = JSON.parse(imagesFileContent);

res.json({ images });
});

app.get('/events/:id', async (req, res) => {
const { id } = req.params;

const eventsFileContent = await fs.readFile('./data/events.json');
const events = JSON.parse(eventsFileContent);

const event = events.find((event) => event.id === id);

if (!event) {
return res
.status(404)
.json({ message: `For the id ${id}, no event could be found.` });
}

setTimeout(() => {
res.json({ event });
}, 1000);
});

app.post('/events', async (req, res) => {
const { event } = req.body;

if (!event) {
return res.status(400).json({ message: 'Event is required' });
}

console.log(event);

if (
!event.title?.trim() ||
!event.description?.trim() ||
!event.date?.trim() ||
!event.time?.trim() ||
!event.image?.trim() ||
!event.location?.trim()
) {
return res.status(400).json({ message: 'Invalid data provided.' });
}

const eventsFileContent = await fs.readFile('./data/events.json');
const events = JSON.parse(eventsFileContent);

const newEvent = {
id: Math.round(Math.random() * 10000).toString(),
...event,
};

events.push(newEvent);

await fs.writeFile('./data/events.json', JSON.stringify(events));

res.json({ event: newEvent });
});

app.put('/events/:id', async (req, res) => {
const { id } = req.params;
const { event } = req.body;

if (!event) {
return res.status(400).json({ message: 'Event is required' });
}

if (
!event.title?.trim() ||
!event.description?.trim() ||
!event.date?.trim() ||
!event.time?.trim() ||
!event.image?.trim() ||
!event.location?.trim()
) {
return res.status(400).json({ message: 'Invalid data provided.' });
}

const eventsFileContent = await fs.readFile('./data/events.json');
const events = JSON.parse(eventsFileContent);

const eventIndex = events.findIndex((event) => event.id === id);

if (eventIndex === -1) {
return res.status(404).json({ message: 'Event not found' });
}

events[eventIndex] = {
id,
...event,
};

await fs.writeFile('./data/events.json', JSON.stringify(events));

setTimeout(() => {
res.json({ event: events[eventIndex] });
}, 1000);
});

app.delete('/events/:id', async (req, res) => {
const { id } = req.params;

const eventsFileContent = await fs.readFile('./data/events.json');
const events = JSON.parse(eventsFileContent);

const eventIndex = events.findIndex((event) => event.id === id);

if (eventIndex === -1) {
return res.status(404).json({ message: 'Event not found' });
}

events.splice(eventIndex, 1);

await fs.writeFile('./data/events.json', JSON.stringify(events));

setTimeout(() => {
res.json({ message: 'Event deleted' });
}, 1000);
});

app.listen(3000, () => {
console.log('Server running on port 3000');
});
1 change: 1 addition & 0 deletions backend/data/events.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"id":"e1","title":"Web Dev Networking Night","description":"Meet, connect, and network with fellow budding web developers. Share your experiences and learn from others.","date":"2024-09-25","time":"18:00","location":"Innovation Lounge, New York, NY","image":"meeting-networking.jpg"},{"id":"e2","title":"City Hunt: Web Dev Edition","image":"buzzing-city.jpg","description":"Explore the city and discover hidden gems while completing fun web development challenges.","date":"2024-10-07","time":"10:00","location":"Tech Training Academy, Los Angeles, CA"},{"id":"e3","title":"Women in Web Development Mixer!","description":"An empowering event dedicated to women who are passionate about web development. Connect, share, and inspire.","date":"2024-05-21","time":"16:30","location":"Empowerment Hall, Seattle, WA","image":"women-coding.jpg"},{"id":"e4","title":"Beginner's Guide to HTML & CSS","description":"Dive into the world of HTML and CSS. This workshop is perfect for those taking their first steps in web development.","date":"2023-11-03","time":"18:30","location":"Learning Labs, Austin, TX","image":"laptop-on-desk.jpg"}]
22 changes: 22 additions & 0 deletions backend/data/images.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"path": "buzzing-city.jpg",
"caption": "People walking through a city buzzing with life at night."
},
{
"path": "laptop-on-desk.jpg",
"caption": "A laptop on a desk."
},
{
"path": "meeting-networking.jpg",
"caption": "A group of people meeting and networking."
},
{
"path": "park.jpg",
"caption": "A park with a lake."
},
{
"path": "women-coding.jpg",
"caption": "A group of women coding."
}
]
Loading

0 comments on commit 1a413f3

Please sign in to comment.