diff --git a/staff/debora-garcia/project/app/src/App.jsx b/staff/debora-garcia/project/app/src/App.jsx index e69de29bb..22dcdf9e7 100644 --- a/staff/debora-garcia/project/app/src/App.jsx +++ b/staff/debora-garcia/project/app/src/App.jsx @@ -0,0 +1,14 @@ +import { Routes, Route } from "react-router-dom" +import Login from "./views/Login"; +import Register from "./views/Register"; +import Home from "./views/Home"; + +export default function App() { + console.log("App -> render") + + return + } /> + } /> + } /> + +} \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/components/Button/index.css b/staff/debora-garcia/project/app/src/components/Button/index.css new file mode 100644 index 000000000..d884fa2ff --- /dev/null +++ b/staff/debora-garcia/project/app/src/components/Button/index.css @@ -0,0 +1,7 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +.Button { + @apply m-[.5rem_0] p-[.4rem] bg-white font-[1rem] rounded-[5px]; + } \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/components/Button/index.jsx b/staff/debora-garcia/project/app/src/components/Button/index.jsx new file mode 100644 index 000000000..70e55b70f --- /dev/null +++ b/staff/debora-garcia/project/app/src/components/Button/index.jsx @@ -0,0 +1,6 @@ +import "./index.css" + +export default function Button({ type, className, onClick, children }) { + return + +} \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/components/Field/index.css b/staff/debora-garcia/project/app/src/components/Field/index.css new file mode 100644 index 000000000..67ee13ae5 --- /dev/null +++ b/staff/debora-garcia/project/app/src/components/Field/index.css @@ -0,0 +1,7 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +.Field { + @apply p-[.3rem] bg-white text-[1rem] rounded-[5px] m-[1rem] w-[80%] ; + } diff --git a/staff/debora-garcia/project/app/src/components/Field/index.jsx b/staff/debora-garcia/project/app/src/components/Field/index.jsx new file mode 100644 index 000000000..7ebaaf273 --- /dev/null +++ b/staff/debora-garcia/project/app/src/components/Field/index.jsx @@ -0,0 +1,8 @@ +import "./index.css" + +export default function Field({ id, type, placeholder }) { + return
+ +
+ +} \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/components/Heading/index.css b/staff/debora-garcia/project/app/src/components/Heading/index.css new file mode 100644 index 000000000..5fc4c3cb8 --- /dev/null +++ b/staff/debora-garcia/project/app/src/components/Heading/index.css @@ -0,0 +1,7 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +.Heading{ + @apply text-[30px] text-[#38383b] +} \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/components/Heading/index.jsx b/staff/debora-garcia/project/app/src/components/Heading/index.jsx new file mode 100644 index 000000000..0eeb78d9d --- /dev/null +++ b/staff/debora-garcia/project/app/src/components/Heading/index.jsx @@ -0,0 +1,7 @@ +import "./index.css" + +export default function Heading({ level, children, className }) { + const Tag = `h${level}` + return {children} + +} \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/index.css b/staff/debora-garcia/project/app/src/index.css index bd6213e1d..2a3a33d0e 100644 --- a/staff/debora-garcia/project/app/src/index.css +++ b/staff/debora-garcia/project/app/src/index.css @@ -1,3 +1,27 @@ @tailwind base; @tailwind components; -@tailwind utilities; \ No newline at end of file +@tailwind utilities; + +:root { + --first-color: rgb(0, 0, 0); + --second-color: rgba(164, 151, 158, 0.776); + } + + * { + font-family: "Courier New", Courier, monospace; + font-style: normal; + color: var(--first-color); + } + + body { + background-color: var(--second-color); + margin: 0; + } + + .registerForm{ + display: flex; + flex-direction: column; + align-items: center; + } + + \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/logic/index.js b/staff/debora-garcia/project/app/src/logic/index.js index e69de29bb..8dc62ad8e 100644 --- a/staff/debora-garcia/project/app/src/logic/index.js +++ b/staff/debora-garcia/project/app/src/logic/index.js @@ -0,0 +1,9 @@ +import loginUser from "./loginUser"; +import registerUser from "./registerUser"; + +const logic = { + registerUser, + loginUser +} + +export default logic \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/logic/loginUser.js b/staff/debora-garcia/project/app/src/logic/loginUser.js new file mode 100644 index 000000000..a76f5d9af --- /dev/null +++ b/staff/debora-garcia/project/app/src/logic/loginUser.js @@ -0,0 +1,33 @@ +import errors, { SystemError } from "com/errors" +import validate from "com/validate" + +const loginUser = (username, password) => { + validate.username(username) + validate.password(password) + + return fetch(`${import.meta.env.VITE_API_URL}/users/auth`, { + method: "POST", + headers: { "Content-type": "application/json" }, + body: JSON.stringify({ username, password }) + }) + .catch(() => { throw new SystemError("server error") }) + .then(response => { + if (response.status === 200) { + return response.json() + .catch(() => { throw new SystemError("server error") }) + .then(token => sessionStorage.token = token) + } + + return response.json() + .catch(() => { throw new SystemError("server error") }) + .then(body => { + const { error, message } = body + + const constructor = errors[error] + + throw new constructor(message) + }) + }) +} + +export default loginUser \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/logic/registerUser.js b/staff/debora-garcia/project/app/src/logic/registerUser.js index e69de29bb..529c436ce 100644 --- a/staff/debora-garcia/project/app/src/logic/registerUser.js +++ b/staff/debora-garcia/project/app/src/logic/registerUser.js @@ -0,0 +1,31 @@ +import errors, { SystemError } from "com/errors" +import validate from "com/validate" + +const registerUser = (name, surname, email, username, password, passwordRepeat) => { + validate.name(name) + validate.name(surname, "surname") + validate.email(email) + validate.username(username) + validate.password(password) + validate.passwordsMatch(password, passwordRepeat) + + return fetch(`${import.meta.env.VITE_API_URL}/users`, { + method: "POST", + headers: { "Content-type": "application/json" }, + body: JSON.stringify({ name, surname, email, username, password, passwordRepeat }) + }) + .catch(() => { throw new SystemError("server error") }) + .then(response => { + if (response.status === 201) return + + return response.json() + .catch(() => { throw new SystemError("server error") }) + .then((body) => { + const { error, message } = body + const constructor = errors[error] + throw new constructor(message) + }) + }) +} + +export default registerUser \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/views/Home.jsx b/staff/debora-garcia/project/app/src/views/Home.jsx new file mode 100644 index 000000000..05e8f0699 --- /dev/null +++ b/staff/debora-garcia/project/app/src/views/Home.jsx @@ -0,0 +1,8 @@ + +export default function Home() { + console.log("Home ->render") + + return <> +

Hola Home!

+ +} \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/views/Login.jsx b/staff/debora-garcia/project/app/src/views/Login.jsx new file mode 100644 index 000000000..99d8cde72 --- /dev/null +++ b/staff/debora-garcia/project/app/src/views/Login.jsx @@ -0,0 +1,46 @@ +import { useNavigate, Link } from "react-router-dom" + +import logic from "../logic" + +import Button from "../components/Button" +import Field from "../components/Field" +import Heading from "../components/Heading" + +export default function Login() { + console.log("Login ->render") + const navigate = useNavigate() + + + const handleLoginSubmit = event => { + event.preventDefault() + + const form = event.target + const username = form.username.value + const password = form.password.value + + try { + logic.loginUser(username, password) + .then(() => navigate("/home")) + .catch(error => { + console.error(error) + alert(error.message) + + }) + + } catch (error) { + console.error(error) + alert(error.message) + } + } + + return
+ WELLCOME BACK! +

Be part of our team

+ + + + + + +
+} \ No newline at end of file diff --git a/staff/debora-garcia/project/app/src/views/Register.jsx b/staff/debora-garcia/project/app/src/views/Register.jsx new file mode 100644 index 000000000..05d7ccf45 --- /dev/null +++ b/staff/debora-garcia/project/app/src/views/Register.jsx @@ -0,0 +1,64 @@ +import { useState } from "react" +import { useNavigate, Link } from "react-router-dom" + +import Button from "../components/Button" +import Field from "../components/Field" +import Heading from "../components/Heading" + +import logic from "../logic" + +export default function Register() { + console.log("Register->render") + + const navigate = useNavigate() + + //const [message, setMessage] = useState("") + + const handleRegisterSubmit = event => { + event.preventDefault() + + const form = event.target + const name = form.name.value + const surname = form.surname.value + const email = form.email.value + const username = form.username.value + const password = form.password.value + const passwordRepeat = form.passwordRepeat.value + + try { + logic.registerUser(name, surname, email, username, password, passwordRepeat) + .then(() => navigate("/login")) + .catch(error => { + console.error(error) + alert(error.message) + + }) + } catch (error) { + console.error(error) + + alert(error.message) + } + + } + + const handleLoginClick = event => { + event.preventDefault() + + navigate("/login") + + } + + return
+ NEW ACCOUNT +

Be part of our team

+ + + + + + + + Login + +
+} diff --git a/staff/debora-garcia/project/doc/README.md b/staff/debora-garcia/project/doc/README.md index 4b39b0ad3..2db345ebc 100644 --- a/staff/debora-garcia/project/doc/README.md +++ b/staff/debora-garcia/project/doc/README.md @@ -1,39 +1,42 @@ # Level Up -Level Up allows users to generate and customize workouts, track personal bests and calculate performance metrics. Users can save workouts and interact with their fitness community. +Level Up allows users to generate and customize workouts, track personal bests and calculate performance metrics. Users can save workouts and interact with their fitness community. ![](https://media.giphy.com/media/w7kBbAW9yrOG2Fni9R/giphy.gif?cid=790b7611608r7er4qfhmfkab26oqm779sm589ngws89in2zz&ep=v1_gifs_search&rid=giphy.gif&ct=g) - - ## Functional ### Use Cases **User** + +- View workout results +- Toggle like workout result +- View wod result coments +- Add coment to workout result +- Delete coment from wod result +- Get random workout +- Share workout result +- Edit wod result +- View own wod results + +**v0.1** + - **Profile** - - Edit personal information - - Add photo/avatar - - Modify username - - Add optional personal data (gender, weight, age) -- **Feed** - - Share workouts and achievements - - Like and comment on posts - - View friends' shared workouts and achievements -- **Workout** - - Generate random workouts - - Customize workouts - - Save workouts with results - - Optionally share workouts on the feed + + - Edit personal information + - Add photo/avatar + - Modify username + - Add optional personal data (gender, weight, age) + - **Achievements** - - Activity: View all recorded workouts - - Analytics: Calculate and estimate weights and repetitions based on personal bests + - Activity: View all recorded workouts + - Analytics: Calculate and estimate weights and repetitions based on personal bests - Add friends to circle ?? - View friends' profiles?? - ### UIUX Design [Figma](https://www.figma.com/proto/iqaqS1n2OJgojcYrg6usIA/LEVEL-UP?page-id=0%3A1&node-id=1-2&viewport=439%2C526%2C0.37&t=ZmB9SD7AMSpINv7N-1&scaling=scale-down&content-scaling=fixed&starting-point-node-id=1%3A2) @@ -56,51 +59,62 @@ Level Up allows users to generate and customize workouts, track personal bests a ### Data Model **User** + - id (string) - name (string) - surname (string) - email (string, unique) - username (string, unique) -- photo or avatar (string, optional) -- gender (string, optional) -- weight (string, optional) -- age (string, optional) or (date, optional) ?? -- friends (list of User.id) **Post** + - id (string) - author (User.id) - image (string,optional) -- description/WOD/Movement (string) -- result (string) +- workout (Workout.id) +- result (Result) - date (date) -- likes (list of User.id) -- comments (list of Comment.id) +- likes ([User.id)] +- comments ([Comment.id]) + +**Result** + +- id (string) +- repetitions (number, optional) +- time (number, optional) +- weight (number, optional) **Workout** + - id (string) -- type (string) -- exercises (list of Movement.id) -- date (date) -- description (string) -- result (string) -- SHARE // SAVE ?? (boolean) +- type (string, enum: emom|amrap|for-time|benchmark) +- exercises ([Movement.id]) +- duration (number) + +**Movement** -**Movements** - id (string) - name (string) - weight (number) - repetitions (number) -- date (date) -**Activity** +**v0.1** + +**Activity** **Anlytics** + - exercises (list of Movement.id) - - reps and weights (1RM, 2RM..) - - percentage and weights (85%, 90%..) + - reps and weights (1RM, 2RM..) + - percentage and weights (85%, 90%..) + - photo or avatar (string, optional) +**Profile** +- gender (string, optional) +- weight (string, optional) +- age (date, optional) +- friends (list of User.id)??