From aa7184518f034dca658c41fe121f5b1e1c350910 Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Sun, 26 May 2024 16:17:43 +0200 Subject: [PATCH 001/126] First commit --- backend/package.json | 4 +++- backend/server.js | 27 +++++++++++++-------------- frontend/package.json | 6 ++++-- frontend/tailwind.config.js | 0 4 files changed, 20 insertions(+), 17 deletions(-) create mode 100644 frontend/tailwind.config.js diff --git a/backend/package.json b/backend/package.json index 08f29f244..d4eababc8 100644 --- a/backend/package.json +++ b/backend/package.json @@ -12,9 +12,11 @@ "@babel/core": "^7.17.9", "@babel/node": "^7.16.8", "@babel/preset-env": "^7.16.11", + "bcrypt": "^5.1.1", "cors": "^2.8.5", "express": "^4.17.3", + "express-list-endpoints": "^7.1.0", "mongoose": "^8.4.0", "nodemon": "^3.0.1" } -} \ No newline at end of file +} diff --git a/backend/server.js b/backend/server.js index 2c00e4802..7f402f205 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,16 +1,13 @@ import express from "express"; import cors from "cors"; -import mongoose from 'mongoose' +import mongoose, { model } from "mongoose"; +import expressListEndpoints from "express-list-endpoints"; +import bcrypt from "bcrypt"; -const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/flowershop" -mongoose.connect(mongoUrl) -mongoose.Promise = Promise +const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/our-wedding"; +mongoose.connect(mongoUrl); +mongoose.Promise = Promise; - - -// Defines the port the app will run on. Defaults to 8080, but can be overridden -// when starting the server. Example command to overwrite PORT env variable value: -// PORT=9000 npm start const port = process.env.PORT || 8080; const app = express(); @@ -19,13 +16,15 @@ app.use(cors()); app.use(express.json()); // Start defining your routes here -// http://localhost:8080/ -app.get("/", (req, res) => { - res.send("Hello Technigo!"); +app.route("/").get(async (req, res) => { + const endpoints = expressListEndpoints(app); + res.json({ + message: "Hello Technigo, welcome to our wedding site API", + endpoints: endpoints, + }); }); - // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); -}); \ No newline at end of file +}); diff --git a/frontend/package.json b/frontend/package.json index 41a2a3164..6a5a63332 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,7 +11,8 @@ }, "dependencies": { "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "zustand": "^4.5.2" }, "devDependencies": { "@types/react": "^18.2.15", @@ -21,6 +22,7 @@ "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", + "tailwindcss": "^3.4.3", "vite": "^4.4.5" } -} \ No newline at end of file +} diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js new file mode 100644 index 000000000..e69de29bb From d1bbfda52dc351a08196a2aa3d9425aa8acc5ff5 Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Sun, 26 May 2024 16:30:00 +0200 Subject: [PATCH 002/126] Update - env and README basics --- README.md | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 31466b54c..1394348c8 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,41 @@ -# Final Project +# Final Project - Our wedding site -Replace this readme with your own information about your project. +## Project Description -Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. +- What your application does +- Why you used the technologies you used +- Some of the challenges you faced and features you hope to implement in the future + +## How to Install and Run the Project + +Provide a step-by-step description of how to get the development environment set and running + +## How to Use the Project + +You can make use of visual aids by including materials like screenshots to show examples of the running project and also the structure and design principles used in your project. + +Also, if your project requires authentication like passwords or usernames, this is a good section to include the credentials. ## The problem -Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next? +## MoSCoW + +Here you can describe the stretch goal(s) and possible features you would like to add in future versions + +### Must have + +### Should have + +### Could have + +### Wont have + +## Collaborators & Credits + +If you worked on the project as a team or an organization, list your collaborators/team members. You should also include links to their GitHub profiles and social media. + +Big thanks to [Citronsskal](https://github.com/Citronskal) and [Trista1987](https://github.com/trista1987) for helping us with the idea and pitch. -## View it live +## See it live -Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. \ No newline at end of file +Deploy your app with Netlify (don’t forget to take care of the routes configuration by adding a .toml file), and paste the link in your README From badb7c3c6d4565735980dae64df22d5bf0afb2ec Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Sun, 26 May 2024 18:16:51 +0200 Subject: [PATCH 003/126] Update - added get and post for guests + model --- backend/README.md | 31 +++++++++++++- backend/server.js | 104 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 133 insertions(+), 2 deletions(-) diff --git a/backend/README.md b/backend/README.md index d1438c910..ed101718c 100644 --- a/backend/README.md +++ b/backend/README.md @@ -5,4 +5,33 @@ This project includes the packages and babel setup for an express server, and is ## Getting Started 1. Install the required dependencies using `npm install`. -2. Start the development server using `npm run dev`. \ No newline at end of file +2. Start the development server using `npm run dev`. + +## Endpoints and routes + +### / + +### /guests + +Example of guest + +``` + { + "firstname": "Test2", + "lastname": "Testsson", + "email": "name@domain.io", + "password": "test", + "plusOne": { + "isAllowed": true, + "name": "Plus One", + "foodChoice": "Fish" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Sister of the bride", + "willAttend": true + } +``` diff --git a/backend/server.js b/backend/server.js index 7f402f205..f0f708b09 100644 --- a/backend/server.js +++ b/backend/server.js @@ -7,6 +7,7 @@ import bcrypt from "bcrypt"; const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/our-wedding"; mongoose.connect(mongoUrl); mongoose.Promise = Promise; +mongoose.set("setDefaultsOnInsert", false); const port = process.env.PORT || 8080; const app = express(); @@ -15,7 +16,63 @@ const app = express(); app.use(cors()); app.use(express.json()); -// Start defining your routes here +const Guest = model("Guest", { + accessToken: { + type: String, + default: () => bcrypt.genSaltSync(), + }, + firstname: { + type: String, + required: true, + }, + lastname: { + type: String, + required: true, + }, + email: { + type: String, + required: true, + }, + password: { + type: String, + required: true, + }, + willAttend: { + type: Boolean, + default: false, + }, + plusOne: { + isAllowed: { type: Boolean, default: false }, + name: { type: String }, + foodChoice: { type: String }, + }, + speech: { + isAllowed: { + type: Boolean, + }, + willMakeSpeech: { + type: Boolean, + default: false, + }, + }, + foodChoice: { + type: String, + }, + relation: { + type: String, + required: true, + }, + // Combine name a unique username + // name: { + // type: String, + // default: () => { + // `${this.firstname} ${this.lastname}`; + // }, + // unique: true, + // }, +}); + +// ROUTES app.route("/").get(async (req, res) => { const endpoints = expressListEndpoints(app); res.json({ @@ -24,6 +81,51 @@ app.route("/").get(async (req, res) => { }); }); +app + .route("/guests") + // Get all guests (specific fields) + .get(async (req, res) => { + const guests = await Guest.find( + {}, + "firstname lastname relation willAttend" + ); + res.send(guests); + }) + // Post new guest + .post(async (req, res) => { + try { + // Deconstruct request body + const { + firstname, + lastname, + email, + password, + plusOne, + speech, + foodChoice, + relation, + willAttend, + } = req.body; + + // Create and save new guest + const newGuest = await new Guest({ + firstname, + lastname, + email, + password: bcrypt.hashSync(password, 10), + plusOne, + speech, + foodChoice, + relation, + willAttend, + }).save(); + + res.status(201).send(`Created guest ID ${newGuest._id}`); + } catch (err) { + res.status(400).json({ message: "Post request failed", error: err }); + } + }); + // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); From 16b032c1ecf99d1520e186dcb524618f9c0e336a Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Sun, 26 May 2024 20:04:15 +0200 Subject: [PATCH 004/126] Update - Seeded DB with guest list + added endpoint for specific guest --- backend/README.md | 17 +- backend/guests.json | 904 ++++++++++++++++++++++++++++++++++++++++++++ backend/server.js | 31 +- 3 files changed, 946 insertions(+), 6 deletions(-) create mode 100644 backend/guests.json diff --git a/backend/README.md b/backend/README.md index ed101718c..f0fbfccfb 100644 --- a/backend/README.md +++ b/backend/README.md @@ -13,17 +13,20 @@ This project includes the packages and babel setup for an express server, and is ### /guests -Example of guest +- .get: get all guests +- .post: post new guest + +#### Example of guest ``` { - "firstname": "Test2", - "lastname": "Testsson", - "email": "name@domain.io", + "firstname": "Judy", + "lastname": "Dench", + "email": "judy@worddomination.io", "password": "test", "plusOne": { "isAllowed": true, - "name": "Plus One", + "name": "Emma Thompson", "foodChoice": "Fish" }, "speech": { @@ -35,3 +38,7 @@ Example of guest "willAttend": true } ``` + +### /guests/:guestId + +- .get: get guest by id diff --git a/backend/guests.json b/backend/guests.json new file mode 100644 index 000000000..400316976 --- /dev/null +++ b/backend/guests.json @@ -0,0 +1,904 @@ +[ + { + "firstname": "John", + "lastname": "Smith", + "email": "john.smith@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Jane Smith", + "foodChoice": "Chicken" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Beef", + "relation": "Groom's father" + }, + { + "firstname": "Jane", + "lastname": "Smith", + "email": "jane.smith@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Chicken", + "relation": "Groom's mother" + }, + { + "firstname": "Michael", + "lastname": "Johnson", + "email": "michael.johnson@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Vegetarian", + "relation": "Groom's friend" + }, + { + "firstname": "Sarah", + "lastname": "Johnson", + "email": "sarah.johnson@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Fish", + "relation": "Bride's mother" + }, + { + "firstname": "Robert", + "lastname": "Wilson", + "email": "robert.wilson@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Elizabeth Brown", + "foodChoice": "Chicken" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Beef", + "relation": "Bride's father" + }, + { + "firstname": "Elizabeth", + "lastname": "Brown", + "email": "elizabeth.brown@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Vegetarian", + "relation": "Robert's girlfriend" + }, + { + "firstname": "James", + "lastname": "Anderson", + "email": "james.anderson@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Mary Anderson", + "foodChoice": "Fish" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Chicken", + "relation": "Groom's friend" + }, + { + "firstname": "Mary", + "lastname": "Anderson", + "email": "mary.anderson@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "James's wife" + }, + { + "firstname": "Joseph", + "lastname": "Thomas", + "email": "joseph.thomas@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Patricia Thomas", + "foodChoice": "Beef" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Fish", + "relation": "Groom's cousin" + }, + { + "firstname": "Patricia", + "lastname": "Thomas", + "email": "patricia.thomas@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Joseph's wife" + }, + { + "firstname": "Christopher", + "lastname": "Harris", + "email": "christopher.harris@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Laura Harris", + "foodChoice": "Chicken" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Beef", + "relation": "Bride's cousin" + }, + { + "firstname": "Laura", + "lastname": "Harris", + "email": "laura.harris@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Christopher's wife" + }, + { + "firstname": "Daniel", + "lastname": "Martin", + "email": "daniel.martin@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Jennifer White", + "foodChoice": "Fish" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Chicken", + "relation": "Groom's coworker" + }, + { + "firstname": "Jennifer", + "lastname": "White", + "email": "jennifer.white@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Daniel's girlfriend" + }, + { + "firstname": "Anthony", + "lastname": "Martinez", + "email": "anthony.martinez@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Karen Martinez", + "foodChoice": "Beef" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Fish", + "relation": "Bride's childhood friend" + }, + { + "firstname": "Karen", + "lastname": "Martinez", + "email": "karen.martinez@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Vegetarian", + "relation": "Anthony's fiancée" + }, + { + "firstname": "Steven", + "lastname": "Rodriguez", + "email": "steven.rodriguez@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Nancy Clark", + "foodChoice": "Chicken" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Beef", + "relation": "Bride's friend" + }, + { + "firstname": "Nancy", + "lastname": "Clark", + "email": "nancy.clark@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Steven's wife" + }, + { + "firstname": "Paul", + "lastname": "Lewis", + "email": "paul.lewis@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Angela Scott", + "foodChoice": "Fish" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Chicken", + "relation": "Groom's college friend" + }, + { + "firstname": "Angela", + "lastname": "Scott", + "email": "angela.scott@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Paul's girlfriend" + }, + { + "firstname": "Joshua", + "lastname": "Allen", + "email": "joshua.allen@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Jessica Adams", + "foodChoice": "Beef" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Fish", + "relation": "Groom's cousin" + }, + { + "firstname": "Jessica", + "lastname": "Adams", + "email": "jessica.adams@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Joshua's wife" + }, + { + "firstname": "Kevin", + "lastname": "Young", + "email": "kevin.young@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Megan Young", + "foodChoice": "Chicken" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Beef", + "relation": "Bride's brother" + }, + { + "firstname": "Megan", + "lastname": "Young", + "email": "megan.young@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Kevin's wife" + }, + { + "firstname": "Jason", + "lastname": "Wright", + "email": "jason.wright@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Samantha Hill", + "foodChoice": "Fish" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Chicken", + "relation": "Groom's colleague" + }, + { + "firstname": "Samantha", + "lastname": "Hill", + "email": "samantha.hill@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Jason's girlfriend" + }, + { + "firstname": "Timothy", + "lastname": "Lopez", + "email": "timothy.lopez@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Rebecca Morgan", + "foodChoice": "Beef" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Fish", + "relation": "Bride's friend" + }, + { + "firstname": "Rebecca", + "lastname": "Morgan", + "email": "rebecca.morgan@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Timothy's wife" + }, + { + "firstname": "Justin", + "lastname": "Green", + "email": "justin.green@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Rachel Moore", + "foodChoice": "Chicken" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Beef", + "relation": "Groom's friend" + }, + { + "firstname": "Rachel", + "lastname": "Moore", + "email": "rachel.moore@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Justin's girlfriend" + }, + { + "firstname": "Brandon", + "lastname": "Adams", + "email": "brandon.adams@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Olivia Edwards", + "foodChoice": "Fish" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Chicken", + "relation": "Groom's cousin" + }, + { + "firstname": "Olivia", + "lastname": "Edwards", + "email": "olivia.edwards@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Brandon's wife" + }, + { + "firstname": "George", + "lastname": "Patterson", + "email": "george.patterson@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Carol Patterson", + "foodChoice": "Beef" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Fish", + "relation": "Bride's friend" + }, + { + "firstname": "Carol", + "lastname": "Patterson", + "email": "carol.patterson@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "George's wife" + }, + { + "firstname": "Susan", + "lastname": "Watson", + "email": "susan.watson@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": true, + "name": "Lisa Watson", + "foodChoice": "Chicken" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Beef", + "relation": "Bride's sister" + }, + { + "firstname": "Lisa", + "lastname": "Watson", + "email": "lisa.watson@example.com", + "password": "password123", + "willAttend": true + +, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": true + }, + "foodChoice": "Vegetarian", + "relation": "Susan's wife" + }, + { + "firstname": "David", + "lastname": "Brown", + "email": "david.brown@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Fish", + "relation": "College friend of the groom" + }, + { + "firstname": "Emily", + "lastname": "Davis", + "email": "emily.davis@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Vegetarian", + "relation": "Bride's cousin" + }, + { + "firstname": "William", + "lastname": "Moore", + "email": "william.moore@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Chicken", + "relation": "Groom's coworker" + }, + { + "firstname": "Linda", + "lastname": "Taylor", + "email": "linda.taylor@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Beef", + "relation": "Bride's neighbor" + }, + { + "firstname": "Charles", + "lastname": "Jackson", + "email": "charles.jackson@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Fish", + "relation": "Groom's uncle" + }, + { + "firstname": "Barbara", + "lastname": "White", + "email": "barbara.white@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Vegetarian", + "relation": "Bride's childhood friend" + }, + { + "firstname": "Matthew", + "lastname": "Thompson", + "email": "matthew.thompson@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Chicken", + "relation": "Groom's high school friend" + }, + { + "firstname": "Susan", + "lastname": "Garcia", + "email": "susan.garcia@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Beef", + "relation": "Bride's college roommate" + }, + { + "firstname": "Mark", + "lastname": "Robinson", + "email": "mark.robinson@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Fish", + "relation": "Bride's colleague" + }, + { + "firstname": "Lisa", + "lastname": "Clark", + "email": "lisa.clark@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Vegetarian", + "relation": "Groom's cousin" + }, + { + "firstname": "Andrew", + "lastname": "Walker", + "email": "andrew.walker@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Chicken", + "relation": "Groom's gym buddy" + }, + { + "firstname": "Michelle", + "lastname": "Hall", + "email": "michelle.hall@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Beef", + "relation": "Bride's colleague" + }, + { + "firstname": "Brian", + "lastname": "Hernandez", + "email": "brian.hernandez@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Fish", + "relation": "Groom's friend" + }, + { + "firstname": "Donna", + "lastname": "King", + "email": "donna.king@example.com", + "password": "password123", + "willAttend": true, + "plusOne": { + "isAllowed": false, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": false, + "willMakeSpeech": false + }, + "foodChoice": "Vegetarian", + "relation": "Bride's aunt" + } +] diff --git a/backend/server.js b/backend/server.js index f0f708b09..ba88a6f46 100644 --- a/backend/server.js +++ b/backend/server.js @@ -3,6 +3,7 @@ import cors from "cors"; import mongoose, { model } from "mongoose"; import expressListEndpoints from "express-list-endpoints"; import bcrypt from "bcrypt"; +import guestData from "./guests.json"; const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/our-wedding"; mongoose.connect(mongoUrl); @@ -72,6 +73,19 @@ const Guest = model("Guest", { // }, }); +// Seed database with guestlist +if (process.env.RESET_DB) { + console.log("Resetting the database!"); + const seedDatabase = async () => { + await Guest.deleteMany({}); + + guestData.forEach(async guest => { + new Guest(guest).save(); + }); + }; + seedDatabase(); +} + // ROUTES app.route("/").get(async (req, res) => { const endpoints = expressListEndpoints(app); @@ -87,7 +101,7 @@ app .get(async (req, res) => { const guests = await Guest.find( {}, - "firstname lastname relation willAttend" + "firstname lastname relation willAttend plusOne.name" ); res.send(guests); }) @@ -126,6 +140,21 @@ app } }); +app + .route("/guests/:guestId") + // Find specific guest + .get(async (req, res) => { + try { + const guest = await Guest.findById( + req.params.guestId, + "_id token firstname lastname relation willAttend plusOne.name" + ).exec(); + res.status(201).json(guest); + } catch (err) { + res.status(400).json({ message: "Used not found", error: err }); + } + }); + // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); From d45ec65ece35180d8e156e057ef515c4f7600951 Mon Sep 17 00:00:00 2001 From: ohitsnathalie <152981339+ohitsnathalie@users.noreply.github.com> Date: Mon, 27 May 2024 18:53:53 +0200 Subject: [PATCH 005/126] setting up tailwind --- frontend/.prettierrc | 3 +++ frontend/package.json | 6 +++++- frontend/postcss.config.js | 6 ++++++ frontend/src/index.css | 3 +++ frontend/tailwind.config.js | 13 +++++++++++++ 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 frontend/.prettierrc create mode 100644 frontend/postcss.config.js diff --git a/frontend/.prettierrc b/frontend/.prettierrc new file mode 100644 index 000000000..b4bfed357 --- /dev/null +++ b/frontend/.prettierrc @@ -0,0 +1,3 @@ +{ + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/frontend/package.json b/frontend/package.json index 6a5a63332..9ddaa2e97 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,11 +18,15 @@ "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", "@vitejs/plugin-react": "^4.0.3", + "autoprefixer": "^10.4.19", "eslint": "^8.45.0", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", + "postcss": "^8.4.38", + "prettier": "^3.2.5", + "prettier-plugin-tailwindcss": "^0.5.14", "tailwindcss": "^3.4.3", - "vite": "^4.4.5" + "vite": "^5.2.11" } } diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js new file mode 100644 index 000000000..2e7af2b7f --- /dev/null +++ b/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/frontend/src/index.css b/frontend/src/index.css index e69de29bb..b5c61c956 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index e69de29bb..ff406f3b9 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -0,0 +1,13 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], + theme: { + screens: { + sm: "320px", + md: "744px", + lg: "1440px", + }, + extend: {}, + }, + plugins: [], +}; From f0d43a6be97e974729b6e2b3fbe4e0a0060c6dd5 Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Tue, 28 May 2024 20:25:12 +0200 Subject: [PATCH 006/126] Update - Added login endpoint and hashed passwords in db seed function --- backend/README.md | 5 +++++ backend/guests.json | 18 +++++++++++++++++ backend/server.js | 49 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/backend/README.md b/backend/README.md index f0fbfccfb..cbe76668e 100644 --- a/backend/README.md +++ b/backend/README.md @@ -11,6 +11,11 @@ This project includes the packages and babel setup for an express server, and is ### / +### /login + +Login to app by using email and password. +Test user: test@example.com | testPassword + ### /guests - .get: get all guests diff --git a/backend/guests.json b/backend/guests.json index 400316976..d0167e0ed 100644 --- a/backend/guests.json +++ b/backend/guests.json @@ -1,4 +1,22 @@ [ + { + "firstname": "Test", + "lastname": "Testsson", + "email": "test@example.com", + "password": "testPassword", + "willAttend": false, + "plusOne": { + "isAllowed": true, + "name": "", + "foodChoice": "" + }, + "speech": { + "isAllowed": true, + "willMakeSpeech": false + }, + "foodChoice": "", + "relation": "Groom's father" + }, { "firstname": "John", "lastname": "Smith", diff --git a/backend/server.js b/backend/server.js index ba88a6f46..7a23f46df 100644 --- a/backend/server.js +++ b/backend/server.js @@ -33,6 +33,7 @@ const Guest = model("Guest", { email: { type: String, required: true, + unique: true, }, password: { type: String, @@ -73,14 +74,36 @@ const Guest = model("Guest", { // }, }); -// Seed database with guestlist +// Seed database with guestlist - temporary solution if (process.env.RESET_DB) { console.log("Resetting the database!"); const seedDatabase = async () => { await Guest.deleteMany({}); guestData.forEach(async guest => { - new Guest(guest).save(); + const { + firstname, + lastname, + email, + password, + plusOne, + speech, + foodChoice, + relation, + willAttend, + } = guest; + + new Guest({ + firstname, + lastname, + email, + password: bcrypt.hashSync(password, 10), + plusOne, + speech, + foodChoice, + relation, + willAttend, + }).save(); }); }; seedDatabase(); @@ -155,6 +178,28 @@ app } }); +//Login +app.route("/login").post(async (req, res) => { + // Find user by name + const guest = await Guest.findOne({ email: req.body.email }).exec(); + console.log(guest); + + // Check if password is correct + if (guest && bcrypt.compareSync(req.body.password, guest.password)) { + // a. User name and password match + res.status(201).json({ + message: "User logged in successfully", + accessToken: guest.accessToken, + }); + } else if (guest) { + // b. user exists but password did not match + res.status(401).json({ message: "Password did not match" }); + } else { + // c. user does not exists + res.status(400).json({ message: "guest name invalid" }); + } +}); + // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); From cc8324ef97d59453f9374db385df724bb9d5c788 Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Wed, 29 May 2024 21:20:54 +0200 Subject: [PATCH 007/126] Update - added patch for updating guest --- backend/README.md | 3 ++ backend/server.js | 80 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 57 insertions(+), 26 deletions(-) diff --git a/backend/README.md b/backend/README.md index cbe76668e..e9d11015e 100644 --- a/backend/README.md +++ b/backend/README.md @@ -11,6 +11,8 @@ This project includes the packages and babel setup for an express server, and is ### / +Se all REST API endpoints + ### /login Login to app by using email and password. @@ -47,3 +49,4 @@ Test user: test@example.com | testPassword ### /guests/:guestId - .get: get guest by id +- .patch: update guest, primarily for RSVP diff --git a/backend/server.js b/backend/server.js index 7a23f46df..d564765d8 100644 --- a/backend/server.js +++ b/backend/server.js @@ -17,6 +17,7 @@ const app = express(); app.use(cors()); app.use(express.json()); +// Mongoose model const Guest = model("Guest", { accessToken: { type: String, @@ -109,6 +110,8 @@ if (process.env.RESET_DB) { seedDatabase(); } +// Auth + // ROUTES app.route("/").get(async (req, res) => { const endpoints = expressListEndpoints(app); @@ -118,13 +121,36 @@ app.route("/").get(async (req, res) => { }); }); +//Login +app.route("/login").post(async (req, res) => { + // Find user by name + const guest = await Guest.findOne({ email: req.body.email }).exec(); + console.log(guest); + + // Check if password is correct + if (guest && bcrypt.compareSync(req.body.password, guest.password)) { + // a. User name and password match + res.status(201).json({ + message: "User logged in successfully", + accessToken: guest.accessToken, + }); + } else if (guest) { + // b. user exists but password did not match + res.status(401).json({ message: "Password did not match" }); + } else { + // c. user does not exists + res.status(400).json({ message: "guest name invalid" }); + } +}); + +// Guests app .route("/guests") - // Get all guests (specific fields) + // Get all guests (specific fields) --- NOT SECURE! Do not share personal info .get(async (req, res) => { const guests = await Guest.find( {}, - "firstname lastname relation willAttend plusOne.name" + "firstname lastname relation willAttend plusOne speech" ); res.send(guests); }) @@ -165,40 +191,42 @@ app app .route("/guests/:guestId") - // Find specific guest + // Find and return specific guest .get(async (req, res) => { try { const guest = await Guest.findById( req.params.guestId, - "_id token firstname lastname relation willAttend plusOne.name" + "_id firstname lastname relation willAttend plusOne.name" ).exec(); res.status(201).json(guest); } catch (err) { - res.status(400).json({ message: "Used not found", error: err }); + res.status(400).json({ message: "User not found", error: err }); } - }); + }) + // Find and update guest + .patch(async (req, res) => { + try { + const guest = await Guest.findById(req.params.guestId).exec(); -//Login -app.route("/login").post(async (req, res) => { - // Find user by name - const guest = await Guest.findOne({ email: req.body.email }).exec(); - console.log(guest); + // Update properties + guest.willAttend = req.body.willAttend; + guest.foodChoice = req.body.foodChoice; + if (guest.plusOne.isAllowed) { + guest.plusOne.name = req.body.plusOne.name; + guest.plusOne.foodChoice = req.body.plusOne.foodChoice; + } + if (guest.speech.isAllowed) { + guest.willMakeSpeech = req.body.willMakeSpeech; + } - // Check if password is correct - if (guest && bcrypt.compareSync(req.body.password, guest.password)) { - // a. User name and password match - res.status(201).json({ - message: "User logged in successfully", - accessToken: guest.accessToken, - }); - } else if (guest) { - // b. user exists but password did not match - res.status(401).json({ message: "Password did not match" }); - } else { - // c. user does not exists - res.status(400).json({ message: "guest name invalid" }); - } -}); + res + .status(201) + // .json(guest); + .json({ message: `Updated guest ID ${guest._id} successfully` }); + } catch (err) { + res.status(400).json({ message: "User not found", error: err }); + } + }); // Start the server app.listen(port, () => { From 4d2e4d54a30bb52b161282441481b880f3245e44 Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Sat, 1 Jun 2024 14:31:27 +0200 Subject: [PATCH 008/126] Update - Pages, sections and components added. NOTE! Sections to me moved to Section folder --- frontend/components/Accordion.jsx | 3 +++ frontend/components/Button.jsx | 3 +++ frontend/components/Carousel.jsx | 3 +++ frontend/components/CarouselCard.jsx | 3 +++ frontend/components/ContactForm.jsx | 3 +++ frontend/components/ContentSection.jsx | 3 +++ frontend/components/Countdown.jsx | 3 +++ frontend/components/FishtankSection.jsx | 3 +++ frontend/components/Heading.jsx | 3 +++ frontend/components/HeroSection.jsx | 3 +++ frontend/components/Icon.jsx | 3 +++ frontend/components/Image.jsx | 3 +++ frontend/components/ImageTextSection.jsx | 3 +++ frontend/components/Input.jsx | 3 +++ frontend/components/List.jsx | 3 +++ frontend/components/LoginForm.jsx | 3 +++ frontend/components/Map.jsx | 3 +++ frontend/components/Party.jsx | 3 +++ frontend/components/PartyCard.jsx | 3 +++ frontend/components/RsvpForm.jsx | 3 +++ frontend/components/Schedule.jsx | 3 +++ frontend/components/VenueSection.jsx | 3 +++ frontend/package.json | 1 + frontend/pages/Homepage.jsx | 5 +++++ frontend/pages/LandingPage.jsx | 5 +++++ frontend/pages/RsvpPage.jsx | 5 +++++ 26 files changed, 82 insertions(+) create mode 100644 frontend/components/Accordion.jsx create mode 100644 frontend/components/Button.jsx create mode 100644 frontend/components/Carousel.jsx create mode 100644 frontend/components/CarouselCard.jsx create mode 100644 frontend/components/ContactForm.jsx create mode 100644 frontend/components/ContentSection.jsx create mode 100644 frontend/components/Countdown.jsx create mode 100644 frontend/components/FishtankSection.jsx create mode 100644 frontend/components/Heading.jsx create mode 100644 frontend/components/HeroSection.jsx create mode 100644 frontend/components/Icon.jsx create mode 100644 frontend/components/Image.jsx create mode 100644 frontend/components/ImageTextSection.jsx create mode 100644 frontend/components/Input.jsx create mode 100644 frontend/components/List.jsx create mode 100644 frontend/components/LoginForm.jsx create mode 100644 frontend/components/Map.jsx create mode 100644 frontend/components/Party.jsx create mode 100644 frontend/components/PartyCard.jsx create mode 100644 frontend/components/RsvpForm.jsx create mode 100644 frontend/components/Schedule.jsx create mode 100644 frontend/components/VenueSection.jsx create mode 100644 frontend/pages/Homepage.jsx create mode 100644 frontend/pages/LandingPage.jsx create mode 100644 frontend/pages/RsvpPage.jsx diff --git a/frontend/components/Accordion.jsx b/frontend/components/Accordion.jsx new file mode 100644 index 000000000..dc5eb834c --- /dev/null +++ b/frontend/components/Accordion.jsx @@ -0,0 +1,3 @@ +export const Accordion = () => { + return
Accordion
; +}; diff --git a/frontend/components/Button.jsx b/frontend/components/Button.jsx new file mode 100644 index 000000000..ba85e761e --- /dev/null +++ b/frontend/components/Button.jsx @@ -0,0 +1,3 @@ +export const Button = () => { + return
Button
; +}; diff --git a/frontend/components/Carousel.jsx b/frontend/components/Carousel.jsx new file mode 100644 index 000000000..cf8e9b102 --- /dev/null +++ b/frontend/components/Carousel.jsx @@ -0,0 +1,3 @@ +export const Carousel = () => { + return
Carousel
; +}; diff --git a/frontend/components/CarouselCard.jsx b/frontend/components/CarouselCard.jsx new file mode 100644 index 000000000..723dc77c2 --- /dev/null +++ b/frontend/components/CarouselCard.jsx @@ -0,0 +1,3 @@ +export const CarouselCard = () => { + return
CarouselCard
; +}; diff --git a/frontend/components/ContactForm.jsx b/frontend/components/ContactForm.jsx new file mode 100644 index 000000000..3b9552dd5 --- /dev/null +++ b/frontend/components/ContactForm.jsx @@ -0,0 +1,3 @@ +export const ContactForm = () => { + return
ContactForm
; +}; diff --git a/frontend/components/ContentSection.jsx b/frontend/components/ContentSection.jsx new file mode 100644 index 000000000..1b4722bc7 --- /dev/null +++ b/frontend/components/ContentSection.jsx @@ -0,0 +1,3 @@ +export const ContentSection = () => { + return
ContentSection
; +}; diff --git a/frontend/components/Countdown.jsx b/frontend/components/Countdown.jsx new file mode 100644 index 000000000..8f1ba2fe5 --- /dev/null +++ b/frontend/components/Countdown.jsx @@ -0,0 +1,3 @@ +export const Countdown = () => { + return
Countdown
; +}; diff --git a/frontend/components/FishtankSection.jsx b/frontend/components/FishtankSection.jsx new file mode 100644 index 000000000..2d2208aa8 --- /dev/null +++ b/frontend/components/FishtankSection.jsx @@ -0,0 +1,3 @@ +export const FishtankSection = () => { + return
FishtankSection
; +}; diff --git a/frontend/components/Heading.jsx b/frontend/components/Heading.jsx new file mode 100644 index 000000000..bf61218d3 --- /dev/null +++ b/frontend/components/Heading.jsx @@ -0,0 +1,3 @@ +export const Heading = () => { + return
Heading
; +}; diff --git a/frontend/components/HeroSection.jsx b/frontend/components/HeroSection.jsx new file mode 100644 index 000000000..8f8deadec --- /dev/null +++ b/frontend/components/HeroSection.jsx @@ -0,0 +1,3 @@ +export const HeroSection = () => { + return
HeroSection
; +}; diff --git a/frontend/components/Icon.jsx b/frontend/components/Icon.jsx new file mode 100644 index 000000000..a0b105442 --- /dev/null +++ b/frontend/components/Icon.jsx @@ -0,0 +1,3 @@ +export const Icon = () => { + return
Icon
; +}; diff --git a/frontend/components/Image.jsx b/frontend/components/Image.jsx new file mode 100644 index 000000000..f82b49e7b --- /dev/null +++ b/frontend/components/Image.jsx @@ -0,0 +1,3 @@ +export const Image = () => { + return
Image
; +}; diff --git a/frontend/components/ImageTextSection.jsx b/frontend/components/ImageTextSection.jsx new file mode 100644 index 000000000..3682ea408 --- /dev/null +++ b/frontend/components/ImageTextSection.jsx @@ -0,0 +1,3 @@ +export const Content = () => { + return
Content
; +}; diff --git a/frontend/components/Input.jsx b/frontend/components/Input.jsx new file mode 100644 index 000000000..574a53c15 --- /dev/null +++ b/frontend/components/Input.jsx @@ -0,0 +1,3 @@ +export const Input = () => { + return
Input
; +}; diff --git a/frontend/components/List.jsx b/frontend/components/List.jsx new file mode 100644 index 000000000..dccf5d5dc --- /dev/null +++ b/frontend/components/List.jsx @@ -0,0 +1,3 @@ +export const List = () => { + return
List
; +}; diff --git a/frontend/components/LoginForm.jsx b/frontend/components/LoginForm.jsx new file mode 100644 index 000000000..e4ff9e54a --- /dev/null +++ b/frontend/components/LoginForm.jsx @@ -0,0 +1,3 @@ +export const LoginForm = () => { + return
LoginForm
; +}; diff --git a/frontend/components/Map.jsx b/frontend/components/Map.jsx new file mode 100644 index 000000000..bc01e9d29 --- /dev/null +++ b/frontend/components/Map.jsx @@ -0,0 +1,3 @@ +export const Map = () => { + return
Map
; +}; diff --git a/frontend/components/Party.jsx b/frontend/components/Party.jsx new file mode 100644 index 000000000..b1be03a61 --- /dev/null +++ b/frontend/components/Party.jsx @@ -0,0 +1,3 @@ +export const Party = () => { + return
Party
; +}; diff --git a/frontend/components/PartyCard.jsx b/frontend/components/PartyCard.jsx new file mode 100644 index 000000000..86e4ba4cf --- /dev/null +++ b/frontend/components/PartyCard.jsx @@ -0,0 +1,3 @@ +export const PartyCard = () => { + return
PartyCard
; +}; diff --git a/frontend/components/RsvpForm.jsx b/frontend/components/RsvpForm.jsx new file mode 100644 index 000000000..6fc6a86b2 --- /dev/null +++ b/frontend/components/RsvpForm.jsx @@ -0,0 +1,3 @@ +export const RsvpForm = () => { + return
RsvpForm
; +}; diff --git a/frontend/components/Schedule.jsx b/frontend/components/Schedule.jsx new file mode 100644 index 000000000..9f5ce6941 --- /dev/null +++ b/frontend/components/Schedule.jsx @@ -0,0 +1,3 @@ +export const Schedule = () => { + return
Schedule
; +}; diff --git a/frontend/components/VenueSection.jsx b/frontend/components/VenueSection.jsx new file mode 100644 index 000000000..709afa53a --- /dev/null +++ b/frontend/components/VenueSection.jsx @@ -0,0 +1,3 @@ +export const VenueSection = () => { + return
VenueSection
; +}; diff --git a/frontend/package.json b/frontend/package.json index 9ddaa2e97..1de9c7542 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,6 +12,7 @@ "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", + "react-router-dom": "^6.23.1", "zustand": "^4.5.2" }, "devDependencies": { diff --git a/frontend/pages/Homepage.jsx b/frontend/pages/Homepage.jsx new file mode 100644 index 000000000..887119061 --- /dev/null +++ b/frontend/pages/Homepage.jsx @@ -0,0 +1,5 @@ +import { Link } from "react-router-dom"; + +export const Homepage = () => { + return
Homepage
; +}; diff --git a/frontend/pages/LandingPage.jsx b/frontend/pages/LandingPage.jsx new file mode 100644 index 000000000..32df68319 --- /dev/null +++ b/frontend/pages/LandingPage.jsx @@ -0,0 +1,5 @@ +import { Link } from "react-router-dom "; + +export const LandingPage = () => { + return
LandingPage
; +}; diff --git a/frontend/pages/RsvpPage.jsx b/frontend/pages/RsvpPage.jsx new file mode 100644 index 000000000..1767450d7 --- /dev/null +++ b/frontend/pages/RsvpPage.jsx @@ -0,0 +1,5 @@ +import { Link } from "react-router-dom"; + +export const RsvpPage = () => { + return
Rsvp
; +}; From 3860327b4357bb11c367b493bd0921781acf330a Mon Sep 17 00:00:00 2001 From: ohitsnathalie <152981339+ohitsnathalie@users.noreply.github.com> Date: Sat, 1 Jun 2024 15:13:56 +0200 Subject: [PATCH 009/126] merge from nav component --- frontend/index.html | 4 ++-- frontend/src/App.jsx | 10 +++++++-- frontend/src/assets/boiler-plate.svg | 18 ---------------- frontend/src/assets/react.svg | 1 - frontend/src/assets/technigo-logo.svg | 31 --------------------------- frontend/src/sections/Header.jsx | 11 ++++++++++ frontend/src/status/Confirmation.jsx | 5 +++++ frontend/src/status/NotFound.jsx | 5 +++++ 8 files changed, 31 insertions(+), 54 deletions(-) delete mode 100644 frontend/src/assets/boiler-plate.svg delete mode 100644 frontend/src/assets/react.svg delete mode 100644 frontend/src/assets/technigo-logo.svg create mode 100644 frontend/src/sections/Header.jsx create mode 100644 frontend/src/status/Confirmation.jsx create mode 100644 frontend/src/status/NotFound.jsx diff --git a/frontend/index.html b/frontend/index.html index 664410b5b..6e6445a38 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,10 +1,10 @@ - + - Technigo React Vite Boiler Plate + Jane & John | We are getting married!
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 0a24275e6..21bf7209e 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,8 +1,14 @@ -export const App = () => { +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { Header } from "./sections/Header"; +import { NotFound } from "./status/NotFound"; +export const App = () => { return ( <> -

Welcome to Final Project!

+ +
+

Wedding Invitation

+ ); }; diff --git a/frontend/src/assets/boiler-plate.svg b/frontend/src/assets/boiler-plate.svg deleted file mode 100644 index c9252833b..000000000 --- a/frontend/src/assets/boiler-plate.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/frontend/src/assets/react.svg b/frontend/src/assets/react.svg deleted file mode 100644 index 6c87de9bb..000000000 --- a/frontend/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/assets/technigo-logo.svg b/frontend/src/assets/technigo-logo.svg deleted file mode 100644 index 3f0da3e57..000000000 --- a/frontend/src/assets/technigo-logo.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/src/sections/Header.jsx b/frontend/src/sections/Header.jsx new file mode 100644 index 000000000..4fbeac7d8 --- /dev/null +++ b/frontend/src/sections/Header.jsx @@ -0,0 +1,11 @@ +import { NavLink } from "react-router-dom"; + +export const Header = () => { + return ( +
+ +
+ ); +}; diff --git a/frontend/src/status/Confirmation.jsx b/frontend/src/status/Confirmation.jsx new file mode 100644 index 000000000..5440faafc --- /dev/null +++ b/frontend/src/status/Confirmation.jsx @@ -0,0 +1,5 @@ +import { Link } from "react-router-dom"; + +export const Confirmation = () => { + return
Confirmation
; +}; diff --git a/frontend/src/status/NotFound.jsx b/frontend/src/status/NotFound.jsx new file mode 100644 index 000000000..3aaf40245 --- /dev/null +++ b/frontend/src/status/NotFound.jsx @@ -0,0 +1,5 @@ +import { Link } from "react-router-dom"; + +export const NotFound = () => { + return
NotFound
; +}; From e4c2bca7ab3e8038eb7e96771761941824c7c7af Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Sat, 1 Jun 2024 15:15:21 +0200 Subject: [PATCH 010/126] Update - added zustand and default store --- frontend/stores/useStore.jsx | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 frontend/stores/useStore.jsx diff --git a/frontend/stores/useStore.jsx b/frontend/stores/useStore.jsx new file mode 100644 index 000000000..1894648af --- /dev/null +++ b/frontend/stores/useStore.jsx @@ -0,0 +1,6 @@ +import { create } from "zustand"; +import { persist, createJSONStorage } from "zustand/middleware"; + +export const useStore = () => { + return
useStore
; +}; From 35a2538e816fb0905fddbe08bd03792ab34ec05c Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Sat, 1 Jun 2024 17:22:04 +0200 Subject: [PATCH 011/126] Update - pair session - pasted tailwind components + started router nav --- frontend/components/Accordion.jsx | 3 - frontend/components/Button.jsx | 3 - frontend/components/HeroSection.jsx | 3 - frontend/pages/Homepage.jsx | 5 - frontend/src/App.jsx | 11 +- frontend/src/components/Accordion.jsx | 189 ++++++++++++++++++ frontend/src/components/Button.jsx | 23 +++ frontend/{ => src}/components/Carousel.jsx | 0 .../{ => src}/components/CarouselCard.jsx | 0 frontend/{ => src}/components/ContactForm.jsx | 0 frontend/{ => src}/components/Countdown.jsx | 0 frontend/{ => src}/components/Heading.jsx | 0 frontend/{ => src}/components/Icon.jsx | 0 frontend/{ => src}/components/Image.jsx | 0 frontend/{ => src}/components/Input.jsx | 0 frontend/{ => src}/components/List.jsx | 0 frontend/{ => src}/components/LoginForm.jsx | 0 frontend/{ => src}/components/Map.jsx | 0 frontend/{ => src}/components/Party.jsx | 0 frontend/{ => src}/components/PartyCard.jsx | 0 frontend/{ => src}/components/RsvpForm.jsx | 0 frontend/{ => src}/components/Schedule.jsx | 0 frontend/src/pages/Homepage.jsx | 11 + frontend/{ => src}/pages/LandingPage.jsx | 2 - frontend/{ => src}/pages/RsvpPage.jsx | 2 - .../sections}/ContentSection.jsx | 0 .../sections}/FishtankSection.jsx | 0 frontend/src/sections/Header.jsx | 6 +- frontend/src/sections/HeroSection.jsx | 63 ++++++ .../sections}/ImageTextSection.jsx | 0 .../sections}/VenueSection.jsx | 0 frontend/src/status/NotFound.jsx | 27 ++- frontend/tailwind.config.js | 21 +- 33 files changed, 345 insertions(+), 24 deletions(-) delete mode 100644 frontend/components/Accordion.jsx delete mode 100644 frontend/components/Button.jsx delete mode 100644 frontend/components/HeroSection.jsx delete mode 100644 frontend/pages/Homepage.jsx create mode 100644 frontend/src/components/Accordion.jsx create mode 100644 frontend/src/components/Button.jsx rename frontend/{ => src}/components/Carousel.jsx (100%) rename frontend/{ => src}/components/CarouselCard.jsx (100%) rename frontend/{ => src}/components/ContactForm.jsx (100%) rename frontend/{ => src}/components/Countdown.jsx (100%) rename frontend/{ => src}/components/Heading.jsx (100%) rename frontend/{ => src}/components/Icon.jsx (100%) rename frontend/{ => src}/components/Image.jsx (100%) rename frontend/{ => src}/components/Input.jsx (100%) rename frontend/{ => src}/components/List.jsx (100%) rename frontend/{ => src}/components/LoginForm.jsx (100%) rename frontend/{ => src}/components/Map.jsx (100%) rename frontend/{ => src}/components/Party.jsx (100%) rename frontend/{ => src}/components/PartyCard.jsx (100%) rename frontend/{ => src}/components/RsvpForm.jsx (100%) rename frontend/{ => src}/components/Schedule.jsx (100%) create mode 100644 frontend/src/pages/Homepage.jsx rename frontend/{ => src}/pages/LandingPage.jsx (62%) rename frontend/{ => src}/pages/RsvpPage.jsx (59%) rename frontend/{components => src/sections}/ContentSection.jsx (100%) rename frontend/{components => src/sections}/FishtankSection.jsx (100%) create mode 100644 frontend/src/sections/HeroSection.jsx rename frontend/{components => src/sections}/ImageTextSection.jsx (100%) rename frontend/{components => src/sections}/VenueSection.jsx (100%) diff --git a/frontend/components/Accordion.jsx b/frontend/components/Accordion.jsx deleted file mode 100644 index dc5eb834c..000000000 --- a/frontend/components/Accordion.jsx +++ /dev/null @@ -1,3 +0,0 @@ -export const Accordion = () => { - return
Accordion
; -}; diff --git a/frontend/components/Button.jsx b/frontend/components/Button.jsx deleted file mode 100644 index ba85e761e..000000000 --- a/frontend/components/Button.jsx +++ /dev/null @@ -1,3 +0,0 @@ -export const Button = () => { - return
Button
; -}; diff --git a/frontend/components/HeroSection.jsx b/frontend/components/HeroSection.jsx deleted file mode 100644 index 8f8deadec..000000000 --- a/frontend/components/HeroSection.jsx +++ /dev/null @@ -1,3 +0,0 @@ -export const HeroSection = () => { - return
HeroSection
; -}; diff --git a/frontend/pages/Homepage.jsx b/frontend/pages/Homepage.jsx deleted file mode 100644 index 887119061..000000000 --- a/frontend/pages/Homepage.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Link } from "react-router-dom"; - -export const Homepage = () => { - return
Homepage
; -}; diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 21bf7209e..672427b82 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,13 +1,22 @@ import { BrowserRouter, Routes, Route } from "react-router-dom"; import { Header } from "./sections/Header"; import { NotFound } from "./status/NotFound"; +import { Homepage } from "./pages/Homepage"; +import { LandingPage } from "./pages/LandingPage"; +import { RsvpPage } from "./pages/RsvpPage"; +import { Confirmation } from "./status/Confirmation"; export const App = () => { return ( <>
-

Wedding Invitation

+

Our wedding site

+ + + + + ); diff --git a/frontend/src/components/Accordion.jsx b/frontend/src/components/Accordion.jsx new file mode 100644 index 000000000..acd2dc6c4 --- /dev/null +++ b/frontend/src/components/Accordion.jsx @@ -0,0 +1,189 @@ +export const Accordion = () => { + return ( +
+
+

+ +

+
+
+

+ Flowbite is an open-source library of interactive components built + on top of Tailwind CSS including buttons, dropdowns, modals, + navbars, and more. +

+

+ Check out this guide to learn how to{" "} + + get started + {" "} + and start developing websites even faster with components on top + of Tailwind CSS. +

+
+
+

+ +

+
+
+

+ Flowbite is first conceptualized and designed using the Figma + software so everything you see in the library has a design + equivalent in our Figma file. +

+

+ Check out the{" "} + + Figma design system + + based on the utility classes from Tailwind CSS and components from + Flowbite. +

+
+
+

+ +

+
+
+

+ The main difference is that the core components from Flowbite are + open source under the MIT license, whereas Tailwind UI is a paid + product. Another difference is that Flowbite relies on smaller and + standalone components, whereas Tailwind UI offers sections of + pages. +

+

+ However, we actually recommend using both Flowbite, Flowbite Pro, + and even Tailwind UI as there is no technical reason stopping you + from using the best of two worlds. +

+

+ Learn more about these technologies: +

+ +
+
+
+ +

+ This accordion component is part of a larger, open-source library of + Tailwind CSS components. Learn more by going to the official{" "} + + Flowbite Documentation + + . +

+ +
+ ); +}; diff --git a/frontend/src/components/Button.jsx b/frontend/src/components/Button.jsx new file mode 100644 index 000000000..65bc57546 --- /dev/null +++ b/frontend/src/components/Button.jsx @@ -0,0 +1,23 @@ +export const Button = ({ cta }) => { + return ( + <> +
+ +
+ + {/* + + */} + + + + ); +}; diff --git a/frontend/components/Carousel.jsx b/frontend/src/components/Carousel.jsx similarity index 100% rename from frontend/components/Carousel.jsx rename to frontend/src/components/Carousel.jsx diff --git a/frontend/components/CarouselCard.jsx b/frontend/src/components/CarouselCard.jsx similarity index 100% rename from frontend/components/CarouselCard.jsx rename to frontend/src/components/CarouselCard.jsx diff --git a/frontend/components/ContactForm.jsx b/frontend/src/components/ContactForm.jsx similarity index 100% rename from frontend/components/ContactForm.jsx rename to frontend/src/components/ContactForm.jsx diff --git a/frontend/components/Countdown.jsx b/frontend/src/components/Countdown.jsx similarity index 100% rename from frontend/components/Countdown.jsx rename to frontend/src/components/Countdown.jsx diff --git a/frontend/components/Heading.jsx b/frontend/src/components/Heading.jsx similarity index 100% rename from frontend/components/Heading.jsx rename to frontend/src/components/Heading.jsx diff --git a/frontend/components/Icon.jsx b/frontend/src/components/Icon.jsx similarity index 100% rename from frontend/components/Icon.jsx rename to frontend/src/components/Icon.jsx diff --git a/frontend/components/Image.jsx b/frontend/src/components/Image.jsx similarity index 100% rename from frontend/components/Image.jsx rename to frontend/src/components/Image.jsx diff --git a/frontend/components/Input.jsx b/frontend/src/components/Input.jsx similarity index 100% rename from frontend/components/Input.jsx rename to frontend/src/components/Input.jsx diff --git a/frontend/components/List.jsx b/frontend/src/components/List.jsx similarity index 100% rename from frontend/components/List.jsx rename to frontend/src/components/List.jsx diff --git a/frontend/components/LoginForm.jsx b/frontend/src/components/LoginForm.jsx similarity index 100% rename from frontend/components/LoginForm.jsx rename to frontend/src/components/LoginForm.jsx diff --git a/frontend/components/Map.jsx b/frontend/src/components/Map.jsx similarity index 100% rename from frontend/components/Map.jsx rename to frontend/src/components/Map.jsx diff --git a/frontend/components/Party.jsx b/frontend/src/components/Party.jsx similarity index 100% rename from frontend/components/Party.jsx rename to frontend/src/components/Party.jsx diff --git a/frontend/components/PartyCard.jsx b/frontend/src/components/PartyCard.jsx similarity index 100% rename from frontend/components/PartyCard.jsx rename to frontend/src/components/PartyCard.jsx diff --git a/frontend/components/RsvpForm.jsx b/frontend/src/components/RsvpForm.jsx similarity index 100% rename from frontend/components/RsvpForm.jsx rename to frontend/src/components/RsvpForm.jsx diff --git a/frontend/components/Schedule.jsx b/frontend/src/components/Schedule.jsx similarity index 100% rename from frontend/components/Schedule.jsx rename to frontend/src/components/Schedule.jsx diff --git a/frontend/src/pages/Homepage.jsx b/frontend/src/pages/Homepage.jsx new file mode 100644 index 000000000..9054610bf --- /dev/null +++ b/frontend/src/pages/Homepage.jsx @@ -0,0 +1,11 @@ +import { Accordion } from "../components/Accordion"; +import { HeroSection } from "../sections/HeroSection"; + +export const Homepage = () => { + return ( +
+ + +
+ ); +}; diff --git a/frontend/pages/LandingPage.jsx b/frontend/src/pages/LandingPage.jsx similarity index 62% rename from frontend/pages/LandingPage.jsx rename to frontend/src/pages/LandingPage.jsx index 32df68319..0b02ab18b 100644 --- a/frontend/pages/LandingPage.jsx +++ b/frontend/src/pages/LandingPage.jsx @@ -1,5 +1,3 @@ -import { Link } from "react-router-dom "; - export const LandingPage = () => { return
LandingPage
; }; diff --git a/frontend/pages/RsvpPage.jsx b/frontend/src/pages/RsvpPage.jsx similarity index 59% rename from frontend/pages/RsvpPage.jsx rename to frontend/src/pages/RsvpPage.jsx index 1767450d7..a83d14af4 100644 --- a/frontend/pages/RsvpPage.jsx +++ b/frontend/src/pages/RsvpPage.jsx @@ -1,5 +1,3 @@ -import { Link } from "react-router-dom"; - export const RsvpPage = () => { return
Rsvp
; }; diff --git a/frontend/components/ContentSection.jsx b/frontend/src/sections/ContentSection.jsx similarity index 100% rename from frontend/components/ContentSection.jsx rename to frontend/src/sections/ContentSection.jsx diff --git a/frontend/components/FishtankSection.jsx b/frontend/src/sections/FishtankSection.jsx similarity index 100% rename from frontend/components/FishtankSection.jsx rename to frontend/src/sections/FishtankSection.jsx diff --git a/frontend/src/sections/Header.jsx b/frontend/src/sections/Header.jsx index 4fbeac7d8..b6d44efc6 100644 --- a/frontend/src/sections/Header.jsx +++ b/frontend/src/sections/Header.jsx @@ -1,10 +1,12 @@ -import { NavLink } from "react-router-dom"; +import { NavLink, Link } from "react-router-dom"; export const Header = () => { return (
); diff --git a/frontend/src/sections/HeroSection.jsx b/frontend/src/sections/HeroSection.jsx new file mode 100644 index 000000000..74672f546 --- /dev/null +++ b/frontend/src/sections/HeroSection.jsx @@ -0,0 +1,63 @@ +import { Image } from "../components/Image"; + +export const HeroSection = () => { + return ( +
+
+ ); +}; diff --git a/frontend/components/ImageTextSection.jsx b/frontend/src/sections/ImageTextSection.jsx similarity index 100% rename from frontend/components/ImageTextSection.jsx rename to frontend/src/sections/ImageTextSection.jsx diff --git a/frontend/components/VenueSection.jsx b/frontend/src/sections/VenueSection.jsx similarity index 100% rename from frontend/components/VenueSection.jsx rename to frontend/src/sections/VenueSection.jsx diff --git a/frontend/src/status/NotFound.jsx b/frontend/src/status/NotFound.jsx index 3aaf40245..86e10d76d 100644 --- a/frontend/src/status/NotFound.jsx +++ b/frontend/src/status/NotFound.jsx @@ -1,5 +1,30 @@ import { Link } from "react-router-dom"; +import { Button } from "../components/Button"; export const NotFound = () => { - return
NotFound
; + return ( +
+
+

404

+

+ Page not found +

+

+ Sorry, we couldn’t find the page you’re looking for. +

+ +
+
+ ); }; diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index ff406f3b9..548a10a7a 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -5,9 +5,26 @@ export default { screens: { sm: "320px", md: "744px", - lg: "1440px", + lg: "1024px", + xl: "1440px", + }, + colors: {}, + fontSize: { + sm: ["16px", { fontWeight: "400" }], + md: ["20px", { fontWeight: "400" }], + "md-bold": ["20px", { fontWeight: "700" }], + lg: ["30px", { fontWeight: "400" }], + "lg-bold": ["30", { fontWeight: "700" }], + xl: ["35px", { fontWeight: "700" }], + "2xl": ["40px", { fontWeight: "700" }], + "3xl": ["55px", { fontWeight: "700" }], + }, + extend: { + fontFamily: { + montserrat: ["Montserrat", "sans-serif"], + cormorant: ["Cormorant", "serif"], + }, }, - extend: {}, }, plugins: [], }; From d5d34151c4faa51b146d6046a8e36ef5526f756a Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Sat, 1 Jun 2024 22:24:16 +0200 Subject: [PATCH 012/126] Update - added routes and navlinks --- frontend/package.json | 1 + frontend/src/App.jsx | 59 +++++--- frontend/src/Root.jsx | 19 +++ frontend/src/components/Accordion.jsx | 188 +------------------------- frontend/src/pages/Homepage.jsx | 4 +- frontend/src/sections/Header.jsx | 10 +- 6 files changed, 71 insertions(+), 210 deletions(-) create mode 100644 frontend/src/Root.jsx diff --git a/frontend/package.json b/frontend/package.json index 1de9c7542..72c293f44 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,6 +12,7 @@ "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", + "react-lazily": "^0.9.2", "react-router-dom": "^6.23.1", "zustand": "^4.5.2" }, diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 672427b82..ad87dcc11 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,23 +1,46 @@ -import { BrowserRouter, Routes, Route } from "react-router-dom"; -import { Header } from "./sections/Header"; +import { createBrowserRouter, RouterProvider } from "react-router-dom"; +import { Root } from "./Root"; import { NotFound } from "./status/NotFound"; -import { Homepage } from "./pages/Homepage"; -import { LandingPage } from "./pages/LandingPage"; -import { RsvpPage } from "./pages/RsvpPage"; import { Confirmation } from "./status/Confirmation"; +import { lazily } from "react-lazily"; + +const { Homepage } = lazily(() => import("./pages/Homepage")); +const { LandingPage } = lazily(() => import("./pages/LandingPage")); +const { RsvpPage } = lazily(() => import("./pages/RsvpPage")); export const App = () => { - return ( - <> - -
-

Our wedding site

- - - - - - - - ); + const router = createBrowserRouter([ + { + path: "/", + // parent route component + element: , + // 404 not found + errorElement: , + // child route components + children: [ + { + index: true, + element: , + }, + { + path: "/login", + element: , + }, + { + path: "/rsvp", + element: , + }, + { + path: "/confirmation", + element: , + }, + // { + // path: "/my-attendance/:guestId", + // element: , + // }, + ], + }, + ]); + + return ; }; diff --git a/frontend/src/Root.jsx b/frontend/src/Root.jsx new file mode 100644 index 000000000..74ea07dec --- /dev/null +++ b/frontend/src/Root.jsx @@ -0,0 +1,19 @@ +import { Outlet, useNavigation } from "react-router-dom"; +import { Header } from "./sections/Header"; +import { Suspense } from "react"; + +export const Root = () => { + const navigation = useNavigation(); + + return ( + <> +
+

Our wedding site

+
+ Loading...}> + + +
+ + ); +}; diff --git a/frontend/src/components/Accordion.jsx b/frontend/src/components/Accordion.jsx index acd2dc6c4..dc5eb834c 100644 --- a/frontend/src/components/Accordion.jsx +++ b/frontend/src/components/Accordion.jsx @@ -1,189 +1,3 @@ export const Accordion = () => { - return ( -
-
-

- -

-
-
-

- Flowbite is an open-source library of interactive components built - on top of Tailwind CSS including buttons, dropdowns, modals, - navbars, and more. -

-

- Check out this guide to learn how to{" "} - - get started - {" "} - and start developing websites even faster with components on top - of Tailwind CSS. -

-
-
-

- -

-
-
-

- Flowbite is first conceptualized and designed using the Figma - software so everything you see in the library has a design - equivalent in our Figma file. -

-

- Check out the{" "} - - Figma design system - - based on the utility classes from Tailwind CSS and components from - Flowbite. -

-
-
-

- -

-
-
-

- The main difference is that the core components from Flowbite are - open source under the MIT license, whereas Tailwind UI is a paid - product. Another difference is that Flowbite relies on smaller and - standalone components, whereas Tailwind UI offers sections of - pages. -

-

- However, we actually recommend using both Flowbite, Flowbite Pro, - and even Tailwind UI as there is no technical reason stopping you - from using the best of two worlds. -

-

- Learn more about these technologies: -

- -
-
-
- -

- This accordion component is part of a larger, open-source library of - Tailwind CSS components. Learn more by going to the official{" "} - - Flowbite Documentation - - . -

- -
- ); + return
Accordion
; }; diff --git a/frontend/src/pages/Homepage.jsx b/frontend/src/pages/Homepage.jsx index 9054610bf..8c5b6a767 100644 --- a/frontend/src/pages/Homepage.jsx +++ b/frontend/src/pages/Homepage.jsx @@ -3,9 +3,9 @@ import { HeroSection } from "../sections/HeroSection"; export const Homepage = () => { return ( -
+ <> -
+ ); }; diff --git a/frontend/src/sections/Header.jsx b/frontend/src/sections/Header.jsx index b6d44efc6..19d421134 100644 --- a/frontend/src/sections/Header.jsx +++ b/frontend/src/sections/Header.jsx @@ -2,10 +2,14 @@ import { NavLink, Link } from "react-router-dom"; export const Header = () => { return ( -
+
From 8531c0adf485aa6f697a44735bcc400e76d44a56 Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Sun, 2 Jun 2024 21:02:34 +0200 Subject: [PATCH 013/126] Update - RSVP form added + fetch for API. Needs fixes still... --- frontend/src/components/RsvpForm.jsx | 363 ++++++++++++++++++++++++++- frontend/src/pages/RsvpPage.jsx | 9 +- 2 files changed, 370 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/RsvpForm.jsx b/frontend/src/components/RsvpForm.jsx index 6fc6a86b2..35196e87b 100644 --- a/frontend/src/components/RsvpForm.jsx +++ b/frontend/src/components/RsvpForm.jsx @@ -1,3 +1,364 @@ +import { useEffect, useState } from "react"; +import { Button } from "./Button"; +import { Icon } from "./Icon"; + +/* State should be set globally and connected to API for real guest data */ + export const RsvpForm = () => { - return
RsvpForm
; + const [plusOne, setPlusOne] = useState(false); + const [rsvp, setRsvp] = useState({ + speech: { + willMakeSpeech: false, + }, + foodChoice: "Select", + willAttend: false, + plusOne: { + name: "", + foodChoice: "Select", + }, + }); + + const API_KEY = import.meta.env.API_KEY; + const API_URL = "http://localhost:8080"; + const guestId = "66561b028575d0e5972fc845"; // FOR DEV, should be loged in ID + const foodOptions = ["Select", "Meat", "Fish", "Vegan"]; + + // API fetch ---- should be moved to store + const patchRsvp = async (event) => { + event.preventDefault(); + try { + const response = await fetch(`${API_URL}/guests/${guestId}`, { + method: "PATCH", + headers: { "Content-Type": "application/json", Authorization: API_KEY }, + body: JSON.stringify(rsvp), + }); + if (!response.ok) { + throw new Error("Error fetching data"); + } + console.log("Patched data", guestId, rsvp); + } catch (error) { + // setErrorMessage("Your thought couldn't be posted..."); + throw new Error("Error", error); + } + }; + + // Handle change in the form + const handleChange = (event) => { + const { name, value, type, checked } = event.target; + const answer = type === "checkbox" ? checked : value; + setRsvp({ ...rsvp, [name]: answer }); + }; + // Handle change for nested object + const handleNested = (event) => { + const { value, type, checked } = event.target; + const answer = type === "checkbox" ? checked : value; + const name = event.target.name.split("."); + setRsvp({ + ...rsvp, + [name[0]]: { ...rsvp[name[0]], [name[1]]: answer }, + }); + }; + + useEffect(() => console.log(rsvp), [rsvp]); + + return ( + /* + This example requires some changes to your config: + + ``` + // tailwind.config.js + module.exports = { + // ... + plugins: [ + // ... + require('@tailwindcss/forms'), + ], + } + ``` +*/ + +
+
+ {/* RSVP section of the form */} +
+ {/* GUEST RSVP */} +
+
+ + My RSVP + +

+ Bla bla bla something about RSVP-ing. +

+
+
+
+ +
+
+ +
+
+ + {rsvp.willAttend && ( +
+
+ +
+
+ +

+ All guest speeches are limited to 5 min each. +

+
+
+ )} + {rsvp.willAttend && ( +
+
+ +
+ +
+
+
+ +
+ + + {errorMessage &&

{errorMessage}

} + {count > 0 && } +
+ ); +}; diff --git a/frontend/src/pages/Messageboard.jsx b/frontend/src/pages/Messageboard.jsx new file mode 100644 index 000000000..618d93a5a --- /dev/null +++ b/frontend/src/pages/Messageboard.jsx @@ -0,0 +1,33 @@ +import { useState } from "react"; +import { Heading } from "../components/Heading"; +import { ThoughtsForm } from "../components/ThoughtsForm"; +import { ThoughtsSection } from "../sections/ThoughtsSection"; + +export const Messageboard = () => { + const [newThought, setNewThought] = useState(""); + + return ( +
+
+
+
+
+ + +
+
+
+
+ +
+
+
+ ); +}; diff --git a/frontend/src/sections/Header.jsx b/frontend/src/sections/Header.jsx index 4c26c9168..3516efa99 100644 --- a/frontend/src/sections/Header.jsx +++ b/frontend/src/sections/Header.jsx @@ -15,6 +15,7 @@ const navigation = [ { name: "Our story", href: "/#story" }, // { name: "RSVP", href: "/rsvp" }, // { name: "My Attendance", href: "/my-attendance" }, + { name: "Message board", href: "/messageboard" }, ]; export const Header = () => { diff --git a/frontend/src/sections/ThoughtsSection.jsx b/frontend/src/sections/ThoughtsSection.jsx new file mode 100644 index 000000000..8fbaaa5fb --- /dev/null +++ b/frontend/src/sections/ThoughtsSection.jsx @@ -0,0 +1,49 @@ +import { useEffect, useState } from "react"; +import { Thought } from "../components/Thought"; +import { Heading } from "../components/Heading"; + +export const ThoughtsSection = ({ newThought }) => { + const [thoughts, setThoughts] = useState([]); + + const API_ENDPOINT = + "https://project-happy-thoughts-api-4mf8.onrender.com/thoughts"; + const METHOD = "GET"; + + //Fetching all thoughts + useEffect(() => { + const fetchThoughts = async () => { + try { + const response = await fetch(API_ENDPOINT, { method: METHOD }); + if (!response.ok) { + throw new Error("Error fetching data"); + } + const data = await response.json(); + setThoughts(data); + } catch (error) { + throw new Error("Error", error); + } + }; + + fetchThoughts(); // Fetch when component is first mounted + + const fetchInterval = setInterval(fetchThoughts, 30000); // Fetch every 60 seconds. + return () => { + clearInterval(fetchInterval); // Clean up the interval when the component unmounts. + }; + }, [newThought]); + + return ( +
+ {/* */} +
+ {thoughts.map((thought) => { + return ; + })} +
+
+ ); +}; diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 62e926800..37d11acf7 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -20,6 +20,7 @@ export default { background: " #DDD7C6", }, fontSize: { + xs: ["12px", { fontWeight: "200" }], sm: ["16px", { fontWeight: "400" }], md: ["20px", { fontWeight: "400" }], "md-bold": ["20px", { fontWeight: "700" }], From 4773f6798d963583d8e89b29744c8f2ebd4abe9e Mon Sep 17 00:00:00 2001 From: Sofia Johansson <153744881+sofia32057@users.noreply.github.com> Date: Thu, 13 Jun 2024 22:41:47 +0200 Subject: [PATCH 096/126] Update - smaller header padding --- frontend/src/sections/Header.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/sections/Header.jsx b/frontend/src/sections/Header.jsx index 3516efa99..4609d12fa 100644 --- a/frontend/src/sections/Header.jsx +++ b/frontend/src/sections/Header.jsx @@ -40,7 +40,7 @@ export const Header = () => { >