Skip to content

Commit

Permalink
Revert "Profile page"
Browse files Browse the repository at this point in the history
  • Loading branch information
IanHollow authored Jun 3, 2024
1 parent 33fa92f commit 0ce170d
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 200 deletions.
29 changes: 2 additions & 27 deletions app/locations/[location]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,14 @@ import {
import { Location } from "@/interfaces/Location";
import { FrontEndReviews } from "@/interfaces/Review";

import { useState, useEffect, useRef } from "react";
import { useCookies } from "react-cookie";
import { useState, useEffect } from "react";

import LocationCategories from "@/components/location/categories";
import Link from "next/link";

export default function Page({ params }: { params: { location: number } }) {
const [location, setLocation] = useState<Location | null>(null);
const [foodReviews, setFoodReviews] = useState<FrontEndReviews | null>(null);
const [cookies] = useCookies(["userEmail", "notificationsEnabled"]);
const alertShown = useRef(false);

const notificationsEnabled = cookies.notificationsEnabled === true;

const user_email = cookies.userEmail || "anonymous";

useEffect(() => {
fetchLocations().then(async (locations: Location[]) => {
Expand All @@ -44,31 +37,13 @@ export default function Page({ params }: { params: { location: number } }) {

fetchFoodReviewsBulk({
food_names: food_names,
user_id: user_email,
user_id: username,
}).then((reviews: FrontEndReviews) => {
setLocation(location);
setFoodReviews(reviews);
});
});
}, [params.location]);
useEffect(() => {
if (
location &&
foodReviews &&
notificationsEnabled &&
!alertShown.current
) {
Object.keys(foodReviews).forEach((foodName) => {
const review = foodReviews[foodName];
if (user_email !== "anonymous" && review.user_rating === 5) {
alert(
`One of your favorite foods is being served! Food: ${foodName}`,
);
alertShown.current = true;
}
});
}
}, [location, foodReviews, notificationsEnabled, user_email]);

if (!location || !foodReviews) {
return <h1>Loading...</h1>;
Expand Down
147 changes: 23 additions & 124 deletions app/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -1,166 +1,65 @@
"use client";
import React, { useEffect, useState } from "react";
import React from "react";
import { useEffect, useState } from "react";
import { googleLogout } from "@react-oauth/google";
import axios from "axios";
import { useCookies } from "react-cookie";
import Image from "next/image";
import { FrontEndReviews } from "@/interfaces/Review";
import { Location } from "@/interfaces/Location";
import { fetchLocations, fetchFoodReviewsBulk, fetchUserInfo } from "@/app/requests";
import { fetchUserInfo } from "@/app/requests";

interface User {
name: string;
email: string;
picture: string;
}

import Image from "next/image";
const imageWidth = 100;
const imageHeight = 100;

const Page = () => {
const [user, setUser] = useState<User | null>(null);
const [cookies, setCookie, removeCookie] = useCookies([
"authToken",
"userEmail",
"notificationsEnabled",
]);
const [reviews, setReviews] = useState<FrontEndReviews>({});
const [notificationsEnabled, setNotificationsEnabled] = useState(
cookies.notificationsEnabled === "true",
);
const [foodNames, setFoodNames] = useState<string[]>([]);
const [loading, setLoading] = useState(true);
const getUserInfo = async () => {
try {
const userInfo = await fetchUserInfo();
setUser(userInfo);
} catch (error) {
console.error("Failed to fetch user info:", error);
}
};
useEffect(() => {
const getUserInfo = async () => {
try {
const access_token = cookies.authToken;

if (!access_token) {
console.error("No access token found");
return;
}

const userInfo = await axios
.get("https://www.googleapis.com/oauth2/v3/userinfo", {
headers: { Authorization: `Bearer ${access_token}` },
})
.then((res) => res.data);

setUser({
name: userInfo.name,
email: userInfo.email,
picture: userInfo.picture,
});
setCookie("userEmail", userInfo.email, { path: "/" });
} catch (error) {
console.error("Error fetching user info:", error);
}
};
const getLocationsAndFoodNames = async () => {
try {
const locations = await fetchLocations();
const allFoodNames = locations.flatMap((location) =>
location.categories.flatMap((category) =>
category.sub_categories.flatMap((sub_category) =>
sub_category.foods.map((food) => food.name),
),
),
);
setFoodNames(allFoodNames);
console.log("Food Names:", allFoodNames);
} catch (error) {
console.error("Error fetching locations and food names:", error);
}
};
getUserInfo();

getLocationsAndFoodNames();
}, [cookies.authToken, cookies.notificationsEnabled, setCookie]);
}, []);

const handleLogout = () => {
googleLogout();
removeCookie("authToken", { path: "/" });
removeCookie("userEmail", { path: "/" });
axios
.post("http://localhost:8000/api/logout/")
.then((res) => console.log("Backend logout successful", res))
.catch((err) => console.error("Backend logout failed", err));

// Remove the token from sessionStorage
sessionStorage.removeItem("token");
// Redirect the user to the main page after logging out
window.location.href = "/";
console.log("Logged out successfully");
};
useEffect(() => {
if (user && user.email) {
fetchReviews(user.email);
}
}, [user, foodNames]);

const fetchReviews = async (userEmail: string) => {
try {
const reviews = await fetchFoodReviewsBulk({
food_names: foodNames,
user_id: userEmail,
});
const filteredReviews = Object.fromEntries(
Object.entries(reviews).filter(
([_, review]) => review.user_rating != null,
),
);
setReviews(filteredReviews);
setLoading(false);
console.log("Fetched Reviews:", filteredReviews);
} catch (error) {
console.error("Error fetching reviews:", error);
}
};

const toggleNotifications = () => {
const newState = !notificationsEnabled;
setNotificationsEnabled(newState);
setCookie("notificationsEnabled", newState.toString(), { path: "/" });

console.log(`Notifications are now ${newState ? "enabled" : "disabled"}`);
};

return (
<div>
<h1 className="text-[#003C6C] font-medium text-xl">Profile</h1>
<h1>Profile</h1>
{user && (
<div>
<Image
src={user.picture}
alt="User profile"
width={imageWidth}
height={imageHeight}
className="rounded-full border-4 border-[#003C6C]"
/>
<h2>
Welcome, {user.name} - {user.email}
</h2>
</div>
)}
<div>
<h2 className="text-[#003C6C] font-medium text-xl">
Your Food Reviews:
</h2>
{loading ? (
<h1>Loading...</h1>
) : (
<ul className="bg-gray-100 p-4 rounded-lg">
{Object.entries(reviews).map(([food_name, review]) => (
<li key={food_name} className="mb-2 text-[#003C6C]">
<h3 className="font-bold">{food_name}</h3>
<p>Rating: {review.user_rating}</p>
</li>
))}
</ul>
)}
</div>
<button
onClick={toggleNotifications}
className="hover:underline decoration-yellow-400 underline-offset-8 top-0 right-0 m-5 p-2 text-[#003C6C] font-medium text-xl"
>
{notificationsEnabled
? "Disable Notifications"
: "Enable Notifications"}
</button>
<button
onClick={handleLogout}
onClick={() => handleLogout()}
className="hover:underline decoration-yellow-400 underline-offset-8 top-0 right-0 m-5 p-2 text-[#003C6C] font-medium text-xl"
>
Logout
Expand Down
4 changes: 2 additions & 2 deletions backend/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ def validate_user(request):
# add user_info to database using get or create possibly

# add current user
# current_user = CurrentUser(request.session)
# request.session["current_user"] = user_info["email"]
current_user = CurrentUser(request.session)
request.session["current_user"] = user_info["email"]

except requests.RequestException as e:
return JsonResponse({"error": "Failed to validate access token"}, status=500)
Expand Down
16 changes: 1 addition & 15 deletions backend/backend/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,7 @@

from pathlib import Path

from private.private_settings import (
DJANGO_SECRET_KEY,
IS_DEV,
DJANGO_GOOGLE_CLIENT_ID,
DJANGO_GOOGLE_CLIENT_SECRET,
)
from private.private_settings import DJANGO_SECRET_KEY, IS_DEV

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = (
Expand All @@ -34,9 +29,6 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = IS_DEV

GOOGLE_CLIENT_ID = DJANGO_GOOGLE_CLIENT_ID
GOOGLE_SECRET_KEY = DJANGO_GOOGLE_CLIENT_SECRET

ALLOWED_HOSTS = [
"127.0.0.1",
"localhost",
Expand Down Expand Up @@ -69,12 +61,6 @@
]

CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_HEADERS = [
"authorization",
"content-type",
"Access-Control-Allow-Origin",
]

ROOT_URLCONF = "backend.urls"

Expand Down
23 changes: 2 additions & 21 deletions components/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
import React, { useEffect, useState } from "react";
import { GoogleOAuthProvider, useGoogleLogin } from "@react-oauth/google";
import axios from "axios";
import { useCookies } from "react-cookie";

import { GOOGLE_CLIENT_ID } from "@/private/secrets";

interface User {
Expand All @@ -20,38 +18,21 @@ const LoginPage = () => {
};

const LoginComponent = () => {
const [user, setUser] = useState<User | null>(null);
const [loggedIn, setLoggedIn] = useState(false);
const [cookies, setCookie] = useCookies(["authToken", "userEmail"]);

useEffect(() => {
console.log("LoginPage component mounted");
}, []);

const handleLogin = useGoogleLogin({
flow: "implicit",

onSuccess: async (tokenResponse) => {
onSuccess: (tokenResponse) => {
console.log(tokenResponse);
// Store authentication token in the browser's storage for navigation bar use
//sessionStorage.setItem("token", tokenResponse.access_token);
const expires = new Date();
expires.setHours(expires.getHours() + 3);
setCookie("authToken", tokenResponse.access_token, {
path: "/",
expires,
});
sessionStorage.setItem("token", tokenResponse.access_token);
// Redirect the user to main page
window.location.href = "/";
//handleLoginSuccess
//client side authentication retrieve user info from access token
const userInfo = await axios
.get("https://www.googleapis.com/oauth2/v3/userinfo", {
headers: { Authorization: `Bearer ${tokenResponse.access_token}` },
})
.then((res) => res.data);
//console.log("userEmail:", userInfo.email);
setCookie("userEmail", userInfo.email, { path: "/", expires });
//send the token to backend
axios
.post("http://localhost:8000/api/users", {
Expand Down
13 changes: 3 additions & 10 deletions components/navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
"use client";
import { useState, useEffect } from "react";
import LoginPage from "./login"; // Used if not logged in
import { useCookies } from "react-cookie";
import Link from "next/link";

export default function Navbar({ height }: { height: string }) {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [cookies] = useCookies(["authToken"]);
/*useEffect(() => {
// Check if sessionStorage is available and if token exists
const token = sessionStorage.getItem("token");
setIsLoggedIn(!!token);
}, []);*/

useEffect(() => {
// Check if the authToken exists in cookies
const token = cookies.authToken;
// Check if sessionStorage is available and if token exists
const token = sessionStorage.getItem("token");
setIsLoggedIn(!!token);
}, [cookies]);
}, []);

return (
<nav className="bg-white fixed w-full top-0 start-0 ">
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"next": "14.2.3",
"prettier": "^3.2.5",
"react": "^18",
"react-cookie": "^7.1.4",
"react-dom": "^18"
},
"devDependencies": {
Expand Down

0 comments on commit 0ce170d

Please sign in to comment.