Skip to content

Commit

Permalink
Merge pull request #60 from jqueja/57-signup-and-log-in-backend-and-f…
Browse files Browse the repository at this point in the history
…ront-end

57 signup and log in backend and front end
  • Loading branch information
joanna-chou authored Dec 1, 2023
2 parents 8440db3 + 50ca232 commit df5c0b8
Show file tree
Hide file tree
Showing 15 changed files with 238 additions and 38 deletions.
Binary file modified .DS_Store
Binary file not shown.
Binary file modified backend/src/__pycache__/database.cpython-311.pyc
Binary file not shown.
Binary file modified backend/src/__pycache__/models.cpython-311.pyc
Binary file not shown.
Binary file modified backend/src/api/__pycache__/info.cpython-311.pyc
Binary file not shown.
Binary file modified backend/src/api/__pycache__/login.cpython-311.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified backend/src/api/__pycache__/signup.cpython-311.pyc
Binary file not shown.
Binary file modified backend/src/api/__pycache__/workouts.cpython-311.pyc
Binary file not shown.
48 changes: 48 additions & 0 deletions backend/src/api/login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from fastapi import APIRouter, Request, HTTPException, status
from sqlalchemy import create_engine, text
import sqlalchemy
from src import database as db
from dotenv import load_dotenv
from fastapi.responses import JSONResponse
from uuid import UUID

load_dotenv()

import os
from supabase import create_client
from pydantic import BaseModel


url = os.environ.get("SUPABASE_URL")
key = os.environ.get("SUPABASE_KEY")
supabase = create_client(url, key)

router = APIRouter(
prefix="/login",
tags=["login"],
)

class LogUserRequest(BaseModel):
user_email: str
user_password: str


@router.post("")
def login_user(request: LogUserRequest):

try:
response = supabase.auth.sign_in_with_password({ "email": request.user_email, "password": request.user_password })


user_id = response.user.id

# Return the user_id in the response
return JSONResponse(content={"user_id": user_id}, status_code=200)

except Exception as e:
# Check if the error is due to invalid credentials
if "Invalid login credentials" in str(e):
raise HTTPException(status_code=401, detail="Invalid credentials")
else:
# Handle other AuthApiError cases as needed
raise HTTPException(status_code=500, detail="Internal server error")
1 change: 1 addition & 0 deletions backend/src/api/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@


app.include_router(settings.router)
app.include_router(login.router)
# app.include_router(login.router)
# app.include_router(login.router)
app.include_router(signup.router)
Expand Down
69 changes: 65 additions & 4 deletions backend/src/api/signup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
import sqlalchemy
from src import database as db
from dotenv import load_dotenv
from fastapi.responses import JSONResponse
from uuid import UUID

load_dotenv()

import os
from supabase import create_client
from pydantic import BaseModel


url = os.environ.get("SUPABASE_URL")
key = os.environ.get("SUPABASE_KEY")
Expand All @@ -18,21 +23,77 @@
)


class CreateUserRequest(BaseModel):
user_email: str
user_password: str
first_name: str
last_name: str

class UserInfo(BaseModel):
id: UUID
weight: int
height: int
age: int
gender: str
dob: str

@router.post("/create-user")
def create_user(user_email: str, user_password: str, first_name: str, last_name: str):
def create_user(request: CreateUserRequest):

with db.engine.begin() as connection:
existing_user_result = connection.execute(
sqlalchemy.text(
"""
SELECT id
FROM users
WHERE email = :user_email
"""),
{"user_email": request.user_email}
)

existing_user = existing_user_result.fetchone()

if existing_user:
# If the email exists, raise an HTTPException with a 400 status code and error message
raise HTTPException(status_code=400, detail="Email already registered")

new_user = supabase.auth.sign_up({ "email": user_email, "password": user_password })
new_user = supabase.auth.sign_up({
"email": request.user_email,
"password": request.user_password
})

user_id = new_user.user.id

with db.engine.begin() as connection:
result = connection.execute(
sqlalchemy.text(
"""
INSERT INTO public_profile (id, first_name, last_name, email)
INSERT INTO users (id, first_name, last_name, email)
VALUES (:user_id, :first_name, :last_name, :user_email)
"""),
{"user_id": user_id, "first_name": first_name, "last_name": last_name, "user_email": user_email}
{"user_id": user_id, "first_name": request.first_name, "last_name": request.last_name, "user_email": request.user_email}
)

# Return the user_id in the response
return JSONResponse(content={"user_id": user_id}, status_code=200)


@router.post("/add-info")
def add_info(request: UserInfo):

print(request)


with db.engine.begin() as connection:
result = connection.execute(
sqlalchemy.text(
"""
UPDATE users
SET weight = :weight, height = :height, age = :age, gender = :gender, dob = :dob
WHERE id = :user_id
"""),
{"user_id": request.id, "weight": request.weight, "height": request.height, "age": request.age,
"gender": request.gender, "dob": request.dob}
)

return "OK"
36 changes: 34 additions & 2 deletions react-frontend/src/components/Info.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState } from "react";
import "./LogSignIn.scss";
import { useNavigate } from "react-router-dom";
import { useLocation } from "react-router-dom";
import white_logo from "../images/WorkoutWhizLogo1White.png";
import Image from "react-bootstrap/Image";
import Row from "react-bootstrap/Row";
Expand All @@ -13,6 +14,8 @@ function Info() {
const [enableButton, setEnableButton] = useState(false);

const navigate = useNavigate();
const location = useLocation();
const userId = location.state?.userId || null; // Get userId from state
const [formData, setFormData] = useState({
weight: "",
height: "",
Expand All @@ -21,6 +24,7 @@ function Info() {
otherText: "",
dob: "",
});

const handleChange = (e) => {
setFormData((formData) => ({
...formData,
Expand All @@ -39,17 +43,45 @@ function Info() {
e.stopPropagation();
}

const formattedUserId = `"${userId}"`.replace(/"/g, "");

// Log the request body before sending the request

// Convert weight, height, and age to numbers
const weight = parseInt(formData.weight, 10);
const height = parseInt(formData.height, 10);
const age = parseInt(formData.age, 10);

// Log the request body before sending the request
const requestBody = {
id: formattedUserId,
weight: weight,
height: height,
age: age,
gender: formData.gender,
dob: formData.dob,
};

console.log("Request Body:", requestBody);

setValidated(true);
if (e.target.checkValidity() === true) {
try {
const response = await fetch(
"http://localhost:3000/signup",
"http://127.0.0.1:8000/signup/add-info",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formData),
body: JSON.stringify({
id: formattedUserId,
weight: parseInt(formData.weight, 10), // Corrected the typo
height: parseInt(formData.height, 10), // Convert height to an integer
age: parseInt(formData.age, 10), // Convert age to an integer
gender: formData.gender,
dob: formData.dob,
}),
}
);

Expand Down
53 changes: 33 additions & 20 deletions react-frontend/src/components/Login.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";

import "./LogSignIn.scss";
import supabase from "./Supabase";
import { useUser } from "../UserContext";
import white_logo from "../images/WorkoutWhizLogo1White.png";
import Image from "react-bootstrap/Image";
Expand All @@ -24,29 +24,42 @@ function Login() {
};

const handleLogin = async () => {
console.log(email);
console.log(password);
try {
let { data: login, error } = await supabase
.from("login")
.select("*")
.eq("email", email)
.eq("password", password);

if (error) {
console.error("Error fetching data:", error.message);
} else {
if (login.length === 0) {
console.log("No match found.");
// Handle no match found case
} else {
setUserId(login[0].id);
console.log("Current userId:", userId);
// Handle successful login, e.g., redirect to a dashboard
// Use history to navigate to the settings page
navigate("/");
}
const response = await fetch("http://127.0.0.1:8000/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
user_email: email,
user_password: password,
}),
});

if (!response.ok) {
console.error("Error during login:", response.statusText);
// Show an alert for login failure
alert("Login failed. Please check your credentials.");
return;
}

const data = await response.json();
const user_id = data.user_id;

setUserId(user_id);

console.log("Current user_id:", user_id);

// Pass the userId using the state object in the navigate function
navigate("/", { state: { userId } });
} catch (error) {
console.error("Error during login:", error.message);
// Show an alert for other errors
alert(
"An unexpected error occurred during login. Please try again."
);
}
};

Expand Down
69 changes: 57 additions & 12 deletions react-frontend/src/components/Signup.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,71 @@ function Signup() {
console.log(passwordMatchError);
}, [formData.confirmPassword, formData.password]);

const handleSubmit = (e) => {
// ... (previous code)

const handleSubmit = async (e) => {
e.preventDefault();
if (formData.password === formData.confirmPassword) {
setPasswordMatchError(false);
} else {

// Check if the password and confirm password match
if (formData.password !== formData.confirmPassword) {
setPasswordMatchError(true);
}

if (e.target.checkValidity() === false || passwordMatchError) {
e.preventDefault();
e.stopPropagation();
}
try {
const response = await fetch(
"http://127.0.0.1:8000/signup/create-user",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
user_email: formData.email,
user_password: formData.password,
first_name: formData.firstName,
last_name: formData.lastName,
}),
}
);

if (!response.ok) {
// Handle error cases, e.g., show an error message
console.error(
"Failed to create user:",
response.statusText
);

try {
const responseBody = await response.json();
if (
response.status === 400 &&
responseBody.detail === "Email already registered"
) {
// Use alert to show a pop-up message
alert(
"Email is already registered. Please use a different email."
);
}
} catch (error) {
// Handle JSON parsing error
console.error("Error parsing JSON response:", error);
}

setValidated(true);
if (e.target.checkValidity() === true && !passwordMatchError) {
console.log("Form data submitted:", formData);
navigate("/info");
return;
}

// Handle success cases, e.g., navigate to the next page
const responseData = await response.json();
const userId = responseData.user_id;
console.log("User created successfully with ID:", userId);
navigate("/info", { state: { userId } });
} catch (error) {
console.error("An error occurred:", error);
}
};

// ... (remaining code)

return (
<section className="vh-100 gradient-custom-light">
<div className="container py-5 h-100 center-items">
Expand Down

0 comments on commit df5c0b8

Please sign in to comment.