);
}
diff --git a/src/components/MediaGrid.tsx b/src/components/MediaGrid.tsx
index f78ca16..2eb7c8f 100644
--- a/src/components/MediaGrid.tsx
+++ b/src/components/MediaGrid.tsx
@@ -1,19 +1,38 @@
import { Masonry } from "masonic";
import MediaCard from "./MediaCard";
+interface Media {
+ src: string;
+ caption: string;
+ id: number;
+ date: Date;
+}
+
interface MediaGridProps {
data: Media[];
+ sortOrder: "latest" | "oldest" | null; // Sorting order as a prop
}
-function MediaGrid({ data }: MediaGridProps) {
+function MediaGrid({ data, sortOrder }: MediaGridProps) {
+ // Sort data based on sortOrder
+ const sortedData = sortOrder
+ ? [...data].sort((a, b) => {
+ return sortOrder === "latest"
+ ? b.date.getTime() - a.date.getTime() // Descending for latest
+ : a.date.getTime() - b.date.getTime(); // Ascending for oldest
+ })
+ : data; // Use default order if sortOrder is null
+
return (
-
+
+
+
);
}
diff --git a/src/components/MemberHeader.tsx b/src/components/MemberHeader.tsx
index 26c80f9..c5a8341 100644
--- a/src/components/MemberHeader.tsx
+++ b/src/components/MemberHeader.tsx
@@ -31,7 +31,7 @@ function MemberHeader({
{profilePicChildren}
-
+
{username}
diff --git a/src/components/NavigationBar.tsx b/src/components/NavigationBar.tsx
index 2238fa3..9bfe7c4 100644
--- a/src/components/NavigationBar.tsx
+++ b/src/components/NavigationBar.tsx
@@ -42,27 +42,27 @@ export function NavigationBar({
//#region Functions
function signOut() {
// Sign out logic for user
- if (
- localStorage.getItem("lastName") &&
- localStorage.getItem("passcode")
- ) {
+ if (userType === "user") {
+
localStorage.removeItem("lastName");
localStorage.removeItem("passcode");
displayToast("Successfully signed out", "success");
setTimeout(() => {
navigate("/login");
}, 2000);
- }
- // Sign out logic for admin
- auth.signOut().then(() => {
- displayToast("Successfully signed out", "success");
- setTimeout(() => {
+ } else if (userType === "admin") {
+
+ // Sign out logic for admin
+ auth.signOut().then(() => {
+ displayToast("Successfully signed out", "success");
+ setTimeout(() => {
+ navigate("/admin/login");
+ }, 2000);
navigate("/admin/login");
- }, 2000);
- navigate("/admin/login");
});
}
+}
//#endregion
return (
diff --git a/src/components/SortDropdownList.tsx b/src/components/SortDropdownList.tsx
index 575d421..8699004 100644
--- a/src/components/SortDropdownList.tsx
+++ b/src/components/SortDropdownList.tsx
@@ -1,82 +1,79 @@
-import { useEffect, useRef, useState } from "react";
-import DropdownItem from "./DropdownItem";
import { CaretDown } from "@phosphor-icons/react";
+import { useEffect, useRef, useState } from "react";
-function SortDropdownList() {
- // Options that can be later add in
- const items = [
- "Newest to Oldest",
- "Oldest to Newest",
- "Most-Least Storage",
- "Recently Updated",
- ];
-
- // State to keep track of the currently selected option
- const [selectedItem, setSelectedItem] = useState(
- null
- ); // useState expect either string or null var
-
- // State to keep track of the menu is being open or not
- const [open, setOpen] = useState(false);
+interface SortDropdownProps {
+ onSelect: (sortOrder: string | null) => void; // null for default sorting
+}
- // Check if user click outside of the menu to close it
- let menuRef = useRef(null); // Typescript like this
+function SortDropdown({ onSelect }: SortDropdownProps) {
+ // State to manage the dropdown open/closed state
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
+ // State to keep track of the current sort order
+ const [sortOrder, setSortOrder] = useState(null); // Default to null
+ // Ref to handle clicks outside the dropdown
+ const dropdownRef = useRef(null);
useEffect(() => {
- let handler = (e: any) => {
- if (menuRef.current && !menuRef.current.contains(e.target)) {
- // Check menuRef.current is not null before calling .contains
- setOpen(false);
+ // Handler to close dropdown when clicking outside of it
+ const handler = (e: MouseEvent) => {
+ if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
+ setIsDropdownOpen(false);
}
};
+ // Add event listener for mouse down
document.addEventListener("mousedown", handler);
-
return () => {
- // Clean up to prevent memory leaks and avoid running outdated event handlers
+ // Clean up the event listener on component unmount
document.removeEventListener("mousedown", handler);
};
}, []);
+ // Function to handle selection of sort order
+ const handleSortSelect = (order: string | null) => {
+ setSortOrder(order); // Update the sort order
+ onSelect(order); // Call the passed in prop to update sort order
+ setIsDropdownOpen(false); // Close the dropdown after selection
+ };
+
return (
-
- {items.map((item, index) => (
- setSelectedItem(item)} // set the selectedItem to that option and when it re-render it will be check by the line above
- />
- ))}
-
- {/* for fun */}
-
- Reset
-
+ {/* Dropdown Menu */}
+ {isDropdownOpen && (
+
+
handleSortSelect("latest")} // Sort by latest
+ >
+ Newest to Oldest
+
+
handleSortSelect("oldest")} // Sort by oldest
+ >
+ Oldest to Newest
+
+
+
handleSortSelect(null)} // Reset to no sorting
+ >
+ Reset
+
+
-
+ )}
);
}
-export default SortDropdownList;
+export default SortDropdown;
diff --git a/src/routes/MemberPage.tsx b/src/routes/MemberPage.tsx
new file mode 100644
index 0000000..6e0a125
--- /dev/null
+++ b/src/routes/MemberPage.tsx
@@ -0,0 +1,201 @@
+import React, { useEffect, useState } from 'react';
+import { ToastContainer } from "react-toastify";
+import { NavigationBar } from "@/components/NavigationBar";
+import MediaGrid from "@/components/MediaGrid";
+import MemberHeader from "@/components/MemberHeader";
+import { useNavigate } from "react-router-dom";
+import profilePic from "@/assets/images/face2.jpg";
+import {CaretDown } from "@phosphor-icons/react";
+import SortDropdownList from "@/components/SortDropdownList";
+import {
+ getFirestore,
+ collection,
+ getDocs,
+ query,
+ where,
+ DocumentData
+
+} from "firebase/firestore";
+import { initializeApp } from "firebase/app";
+
+
+// Temporary data for media grid
+const data = [
+ // Array of media items with image source, caption, ID, and date
+
+ {
+ src: "https://images.unsplash.com/photo-1724579243894-6a8c9bbfe88c",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1234,
+ date: new Date("Oct 5, 2024"),
+ },
+ {
+ src: "https://images.unsplash.com/photo-1723984834599-5357b87f727c",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1235,
+ date: new Date("Oct 4, 2024"),
+ },
+ {
+ src: "https://images.unsplash.com/photo-1724505599369-2c1d43324fdc",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1236,
+ date: new Date("Oct 3, 2024"),
+ },
+ {
+ src: "https://images.unsplash.com/photo-1724579243894-6a8c9bbfe88c",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1237,
+ date: new Date("Oct 7, 2024"),
+ },
+ {
+ src: "https://images.unsplash.com/photo-1723984834599-5357b87f727c",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1238,
+ date: new Date("Oct 8, 2024"),
+ },
+ {
+ src: "https://images.unsplash.com/photo-1724505599369-2c1d43324fdc",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1239,
+ date: new Date("Oct 2, 2024"),
+ },
+ {
+ src: "https://images.unsplash.com/photo-1724579243894-6a8c9bbfe88c",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1240,
+ date: new Date("Oct 2, 2024"),
+ },
+ {
+ src: "https://images.unsplash.com/photo-1723984834599-5357b87f727c",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1241,
+ date: new Date("Oct 2, 2024"),
+ },
+ {
+ src: "https://images.unsplash.com/photo-1724505599369-2c1d43324fdc",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1242,
+ date: new Date("Oct 9, 2024"),
+ },
+ {
+ src: "https://images.unsplash.com/photo-1724579243894-6a8c9bbfe88c",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1240,
+ date: new Date("Oct 10, 2024"),
+ },
+ {
+ src: "https://images.unsplash.com/photo-1723984834599-5357b87f727c",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1241,
+ date: new Date("Oct 2, 2024"),
+ },
+ {
+ src: "https://images.unsplash.com/photo-1724505599369-2c1d43324fdc",
+ caption:
+ "Channeling their inner artist with a paintbrush and a splash of color!",
+ id: 1242,
+ date: new Date("Oct 2, 2024"),
+ },
+];
+
+
+//#region firebase
+const firebaseConfig = JSON.parse(import.meta.env.VITE_FIREBASE_CONFIG);
+const app = initializeApp(firebaseConfig);
+const database = getFirestore(app);
+const usersRef = collection(database, "users");
+//#endregion
+
+export default function MemberPage() {
+ const navigate = useNavigate();
+ const [sortOrder, setSortOrder] = useState<"latest" | "oldest" | null>(null);
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
+ const [userData, setUserData] = useState(null);
+
+
+ type SortOrder = "latest" | "oldest";
+
+ // Check for user login info in localStorage and fetch user data from Firebase
+ useEffect(() => {
+ const fetchData = async () => {
+ const lastName = localStorage.getItem("lastName");
+ const passcode = localStorage.getItem("passcode");
+ if (!lastName || !passcode) {
+ // Redirect to login page if lastName or passcode is missing
+ navigate("/login");
+ return;
+ }
+ // Firebase query to find user with matching lastName and passcode
+ const q = query(
+ collection(database, "users"),
+ where("lastName", "==", lastName),
+ where("passcode", "==", passcode)
+ );
+
+ const querySnapshot = await getDocs(q);
+ if (!querySnapshot.empty) {
+ const userDoc = querySnapshot.docs[0].data(); // Set retrieved user data to userData state
+ setUserData(userDoc);
+ } else {
+ navigate("/login"); // Redirect to login if no user matches
+ }
+ };
+
+ fetchData();
+ }, [navigate]);
+
+ // Function to update sortOrder and close the dropdown menu
+ const handleSortSelect = (order: "latest" | "oldest" | null) => {
+ setSortOrder(order); // Update sort order (latest or oldest)
+ setIsDropdownOpen(false); // Close dropdown after selection
+ };
+
+ return (
+
+ {/* Toast notification container */}
+
+ {/* Navigation bar for the user type "user" */}
+
+
+ {/* Display user header with profile picture and username if userData is available */}
+
+ {userData && (
+
+ }
+ />
+ )}
+
+ {/* SortDropdownList component for choosing sort order */}
+
+
+ {/* temporary */}
+
+
+ {/* MediaGrid component to display sorted media items */}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/routes/caregiver/CaregiverLogin.tsx b/src/routes/caregiver/CaregiverLogin.tsx
index eefb4e6..707ec8a 100644
--- a/src/routes/caregiver/CaregiverLogin.tsx
+++ b/src/routes/caregiver/CaregiverLogin.tsx
@@ -54,7 +54,10 @@ export default function CaregiverLogin() {
// User found
if (user.docs.length > 0) {
console.log("Signed in as: ", user.docs[0].data().lastName);
+ localStorage.setItem("lastName", userLastName);
+ localStorage.setItem("passcode", userPasscode);
navigate("/");
+
}
// User not found