diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml
index 51c6c45..653cb97 100644
--- a/.github/workflows/firebase-hosting-pull-request.yml
+++ b/.github/workflows/firebase-hosting-pull-request.yml
@@ -3,6 +3,8 @@
name: Deploy to Firebase Hosting on PR
'on': pull_request
+env:
+ VITE_FIREBASE_CONFIG: ${{ secrets.VITE_FIREBASE_CONFIG}}
jobs:
build_and_preview:
if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}'
@@ -18,3 +20,5 @@ jobs:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_SCAFFOLD_TOOL }}'
projectId: alzheimercalgary-v2
+ env:
+ VITE_FIREBASE_CONFIG: ${{ secrets.VITE_FIREBASE_CONFIG}}
diff --git a/.gitignore b/.gitignore
index 749d71c..5fd29ca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,5 @@ package-lock.json
# Local Netlify folder
.netlify
+config.tsx
+.env
\ No newline at end of file
diff --git a/package.json b/package.json
index e10a899..c356599 100644
--- a/package.json
+++ b/package.json
@@ -12,9 +12,11 @@
"dependencies": {
"@phosphor-icons/react": "^2.0.15",
"clsx": "^2.1.0",
+ "firebase": "^10.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.9.0",
+ "react-toastify": "^10.0.5",
"tailwind-merge": "^2.2.1"
},
"devDependencies": {
diff --git a/src/App.tsx b/src/App.tsx
index f425d5a..724f929 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,30 +1,32 @@
//#region import
import { createBrowserRouter, RouterProvider } from "react-router-dom";
-// routes
-import ButtonTestRoute from "@/routes/ButtonTestRoute";
-import ProfilePictureTest from "./routes/ProfilePictureTestRoute";
-import Test from "./routes/Test";
-import SearchBarTest from "./routes/SearchBarTestRoute";
-import SortDropdownListTestRoute from "@/routes/SortDropdownListTestRoute";
-import NavigationTest from "@/routes/NavigationTest";
-import TooltipTestRoute from "./routes/TooltipTestRoute";
-import InputCodeTest from "@/routes/InputCodeTest";
-import ToastTestRoute from "@/routes/ToastTestRoute";
-import MediaUploadZoneTestRoute from "@/routes/MediaUploadZoneTestRoute";
-import IconOptionTest from "./routes/IconOptionTest";
-import ImageTestRoute from "./routes/ImageTestRoute";
-import { MemberTableTestRoute } from "./routes/MemberTableTestRoute";
-import ColorPickerTestRoute from "@/routes/ColorPickerTestRoute";
-import InputFieldTestRoute from "./routes/InputFieldTestRoute";
-import MemberHeaderTestRoute from "@/routes/MemberHeaderTestRoute";
-import MediaUploadStatusTestRoute from "./routes/MediaUploadStatusTestRoute";
-import ModalTestRoute from "@/routes/ModalTestRoute";
-import GalleryTestRoute from "./routes/GalleryTestRoute";
+// test routes
+import ButtonTestRoute from "@/routes/test/ButtonTestRoute";
+import ProfilePictureTest from "./routes/test/ProfilePictureTestRoute";
+import Test from "./routes/test/Test";
+import SearchBarTest from "./routes/test/SearchBarTestRoute";
+import SortDropdownListTestRoute from "@/routes/test/SortDropdownListTestRoute";
+import NavigationTest from "@/routes/test/NavigationTest";
+import TooltipTestRoute from "./routes/test/TooltipTestRoute";
+import InputCodeTest from "@/routes/test/InputCodeTest";
+import ToastTestRoute from "@/routes/test/ToastTestRoute";
+import MediaUploadZoneTestRoute from "@/routes/test/MediaUploadZoneTestRoute";
+import IconOptionTest from "./routes/test/IconOptionTest";
+import ImageTestRoute from "./routes/test/ImageTestRoute";
+import { MemberTableTestRoute } from "./routes/test/MemberTableTestRoute";
+import ColorPickerTestRoute from "@/routes/test/ColorPickerTestRoute";
+import InputFieldTestRoute from "./routes/test/InputFieldTestRoute";
+import MemberHeaderTestRoute from "@/routes/test/MemberHeaderTestRoute";
+import MediaUploadStatusTestRoute from "./routes/test/MediaUploadStatusTestRoute";
+import ModalTestRoute from "@/routes/test/ModalTestRoute";
+import GalleryTestRoute from "./routes/test/GalleryTestRoute";
import { MemberInformation } from "./components/MemberInformation";
import { LoginModal } from "./components/LoginModal";
-import MemberProfilePictureTest from "@/routes/MemberProfilePictureTest";
+import MemberProfilePictureTest from "@/routes/test/MemberProfilePictureTest";
+// routes
+import AdminLogin from "./routes/admin/AdminLogin";
const router = createBrowserRouter([
{
@@ -99,29 +101,14 @@ const router = createBrowserRouter([
path: "/modal-test",
element: ,
},
- {
- path: "/login-modal-test",
- element: (
-
-
-
-
- ),
- },
{
path: "/member-table",
element: ,
},
- {
- path: "/image-overlay",
- element:
- },
+ {
+ path: "/image-overlay",
+ element: ,
+ },
{
path: "/MediaUploadStatusTest",
element: ,
@@ -134,10 +121,24 @@ const router = createBrowserRouter([
path: "/member-profile-picture-test",
element: ,
},
+
+ // Admin routes
+ {
+ path: "/admin",
+ element: (
+
+ ),
+ },
+ {
+ path: "/admin/login",
+ element: ,
+ },
]);
function App() {
- return ;
+ return ;
}
export default App;
diff --git a/src/components/Button.tsx b/src/components/Button.tsx
index 04dcb01..712e4da 100644
--- a/src/components/Button.tsx
+++ b/src/components/Button.tsx
@@ -1,63 +1,63 @@
import { useRef } from "react";
import { twMerge } from "tailwind-merge";
interface ButtonProps extends React.ButtonHTMLAttributes {
- onClick?: () => void;
- icon?: React.ElementType;
- text?: string;
- rounded?: boolean;
- fill?: boolean;
- status?: string;
- fontSize?: string;
- color?: string;
+ onClick?: React.MouseEventHandler;
+ icon?: React.ElementType;
+ text?: string;
+ rounded?: boolean;
+ fill?: boolean;
+ disabled: boolean;
+ fontSize?: string;
+ color?: string;
}
const Button: React.FC = ({
- text = null,
- icon: Icon = null,
- onClick = () => console.log("Clicked"),
- rounded = false,
- fill = true,
- status = "enabled",
- fontSize = "1em",
- className = null,
+ text = null,
+ icon: Icon = null,
+ onClick,
+ rounded = false,
+ fill = true,
+ disabled = false,
+ fontSize = "1em",
+ className = null,
}) => {
- const buttonRef = useRef(null);
- const buttonClassName = twMerge(
- `flex flex-row items-center justify-center p-4 ${
- status === "disabled"
- ? "bg-neutrals-light-200 text-gray-400 cursor-default"
- : fill
- ? "relative overflow-hidden bg-primary-main text-white z-10 active:bg-primary-main active:text-white transition-colors hover:bg-neutrals-light-100 hover:text-primary-main border-2 border-primary-main hover:border-primary-main rounded-full w-full h-full before:absolute before:right-0 before:top-0 before:w-full before:h-full before:z-0 before:bg-primary-main before:content[''] before:transition-transform before:duration-300 hover:before:transform hover:before:translate-x-full"
- : "relative overflow-hidden text-primary-dark border-primary-dark border-2 active:bg-white active:text-primary-dark transition-colors before:absolute before:left-0 before:top-0 before:-z-10 before:h-full before:w-full before:origin-top-left before:scale-x-0 before:bg-primary-dark before:transition-transform before:duration-300 before:content-[''] hover:text-white before:hover:scale-x-100"
- } ${rounded ? "rounded-full" : "rounded-lg"} w-full h-full`,
- className
- // change color --> change text-{color}, border-{color} and active:bg-{color}, active:text-{color}, before:bg-{color}
- );
+ const buttonRef = useRef(null);
+ const buttonClassName = twMerge(
+ `flex flex-row items-center justify-center p-4 ${
+ disabled === true
+ ? "bg-neutrals-light-200 text-gray-400 cursor-default"
+ : fill
+ ? "relative overflow-hidden bg-primary-main text-white z-10 active:bg-primary-main active:text-white transition-colors hover:bg-neutrals-light-100 hover:text-primary-main border-2 border-primary-main hover:border-primary-main rounded-full w-full h-full before:absolute before:right-0 before:top-0 before:w-full before:h-full before:z-0 before:bg-primary-main before:content[''] before:transition-transform before:duration-300 hover:before:transform hover:before:translate-x-full"
+ : "relative overflow-hidden text-primary-dark border-primary-dark border-2 active:bg-white active:text-primary-dark transition-colors before:absolute before:left-0 before:top-0 before:-z-10 before:h-full before:w-full before:origin-top-left before:scale-x-0 before:bg-primary-dark before:transition-transform before:duration-300 before:content-[''] hover:text-white before:hover:scale-x-100"
+ } ${rounded ? "rounded-full" : "rounded-lg"} w-full h-full`,
+ className,
+ // change color --> change text-{color}, border-{color} and active:bg-{color}, active:text-{color}, before:bg-{color}
+ );
- return (
-
- );
+ return (
+
+ );
};
export default Button;
diff --git a/src/components/InputField.tsx b/src/components/InputField.tsx
index 3de1a58..32cbaba 100644
--- a/src/components/InputField.tsx
+++ b/src/components/InputField.tsx
@@ -3,88 +3,101 @@ import { useRef, useState } from "react";
import { Eye, EyeSlash } from "@phosphor-icons/react";
export interface InputFieldProps {
- type: string;
- error: boolean;
- label?: string; // Optional; Default to none.
- required: boolean;
- placeholder?: string;
+ type: string;
+ error: boolean;
+ label?: string; // Optional; Default to none.
+ required: boolean;
+ placeholder?: string;
- // set Field value
- setInput: (input: string) => void;
+ // set Field value
+ setInput: React.Dispatch>;
}
function InputField({
- type,
- error,
- label,
- required,
- placeholder,
- setInput,
+ type,
+ error,
+ label,
+ required,
+ placeholder,
+ setInput,
}: InputFieldProps) {
- const inputRef = useRef(null);
- const [showPassword, setShowPassword] = useState(false);
+ const inputRef = useRef(null);
+ const [showPassword, setShowPassword] = useState(false);
+ const [showError, setShowError] = useState(false);
- function checkLen(event: { preventDefault: () => void }) {
- event.preventDefault();
- if (inputRef.current) {
- if (inputRef.current.value.trim() === "" && required === true) {
- console.log("Required Input is empty");
- }
- }
- }
+ function validateInput(event: { preventDefault: () => void }) {
+ event.preventDefault();
- return (
-
- {/* Label */}
-
-
- {required && *}
-
+ if (inputRef.current) {
+ setInput(inputRef.current.value);
+ if (inputRef.current.value.trim() === "" && required === true) {
+ setShowError(true);
+ }
+ if (type === "email") {
+ const email = inputRef.current.value.trim();
+ const emailRegex =
+ /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
+ const valid = emailRegex.test(email);
+ setShowError(!valid);
+ } else if (type === "password") {
+ const password = inputRef.current.value.trim();
+ password.length < 6 ? setShowError(true) : setShowError(false);
+ }
+ }
+ }
- {/* Input */}
-
-
setInput(e.target.value)}
- >
+ return (
+
+ {/* Label */}
+
+
+ {required && *}
+
- {type.toLowerCase() === "password" && !showPassword && (
-
setShowPassword(!showPassword)}
- />
- )}
+ {/* Input */}
+
+ validateInput(e)}
+ >
- {/* Show password button */}
- {type.toLowerCase() === "password" && showPassword && (
- setShowPassword(!showPassword)}
- />
- )}
-
+ {type.toLowerCase() === "password" && !showPassword && (
+ setShowPassword(!showPassword)}
+ />
+ )}
- {/* Error */}
- {error && (
-
-
-
- Error {type}{" "}
-
-
- )}
-
- );
+ {/* Show password button */}
+ {type.toLowerCase() === "password" && showPassword && (
+
setShowPassword(!showPassword)}
+ />
+ )}
+
+
+ {/* Error */}
+ {showError && (
+
+
+
+ Invalid {type}
+
+
+ )}
+
+ );
}
export default InputField;
diff --git a/src/components/LoginModal.tsx b/src/components/LoginModal.tsx
index e0259bd..a01aaec 100644
--- a/src/components/LoginModal.tsx
+++ b/src/components/LoginModal.tsx
@@ -1,7 +1,7 @@
//#region Imports
import logoUrl from "@/assets/images/asc_logo.svg";
import { twMerge } from "tailwind-merge";
-import { useState } from "react";
+import React, { useState } from "react";
import Button from "./Button";
import InputField from "./InputField";
@@ -10,20 +10,41 @@ import { InputCode } from "./InputCode";
//#region Interface
interface LoginModalProps {
- /**
- * Additional TailwindCSS classes.
- */
- className?: string;
+ /**
+ * Additional TailwindCSS classes.
+ */
+ className?: string;
- /**
- * The title of the login modal.
- */
- title: string;
+ /**
+ * The title of the login modal.
+ */
+ title: string;
- /**
- * The type of the login modal.
- */
- type: "admin" | "member";
+ /**
+ * The type of the login modal.
+ */
+ type: "admin" | "member";
+
+ /**
+ * The email of the user.
+ */
+ email: string;
+ setEmail: React.Dispatch>;
+
+ /**
+ * The password of the user.
+ */
+ password?: string;
+ setPassword?: React.Dispatch>;
+
+ /**
+ * The passcode of the user.
+ */
+ passcode?: Record;
+ setPasscode?: React.Dispatch>>;
+
+ /** */
+ onClick: React.MouseEventHandler;
}
//#endregion
@@ -32,73 +53,93 @@ interface LoginModalProps {
* @param {string} title - The title of the login modal.
* @param {string} className - Additional TailwindCSS.
* @param {string} type - The type of the login modal.
+ * @param {string} email - The email of the user.
+ * @param {string} password - The password of the user.
+ * @param {Record} passcode - The passcode of the user.
+ * @param {Function} setEmail - Set the email of the user.
+ * @param {Function} setPassword - Set the password of the user.
+ * @param {Function} setPasscode - Set the passcode of the user.
* @returns
*/
-const LoginModal = ({ className, title, type }: LoginModalProps) => {
- // TODO: Authentication functionality
- const [username, setUsername] = useState("");
- const [password, setPassword] = useState("");
- const [passcode, setPasscode] = useState>({
- 0: "",
- 1: "",
- 2: "",
- 3: "",
- 4: "",
- 5: "",
- });
+const LoginModal = ({
+ className,
+ title,
+ type,
+ email,
+ setEmail,
+ password,
+ setPassword,
+ passcode,
+ setPasscode,
+ onClick,
+}: LoginModalProps) => {
+ const [validEmail, setValidEmail] = useState(false);
+ // const [passcode, setPasscode] = useState>({
+ // 0: "",
+ // 1: "",
+ // 2: "",
+ // 3: "",
+ // 4: "",
+ // 5: "",
+ // });
- return (
-
- {/* Logo */}
-
+ return (
+
+ {/* Logo */}
+
- {/* Title */}
-
{title}
+ {/* Title */}
+
+ {title}
+
- {/*Username field */}
-
+ {/*Username field */}
+
- {/* Password field */}
- {type === "admin" ? (
-
- ) : (
-
- )}
+ {/* Password field */}
+ {type === "admin" ? (
+
+ ) : (
+
+ )}
- {/* Login Button */}
-
-
- );
+ {/* Login Button */}
+
+
+ );
};
export { LoginModal };
diff --git a/src/components/Toast.tsx b/src/components/Toast.tsx
index 96142dd..f2a6dfe 100644
--- a/src/components/Toast.tsx
+++ b/src/components/Toast.tsx
@@ -1,58 +1,80 @@
import clsx from "clsx";
-import { Warning, WarningCircle, Check, Info } from "@phosphor-icons/react";
-
+import { Warning, WarningCircle, Check, Info } from "@phosphor-icons/react";
interface ToastIconProps {
- /** The theme of the toast */
- severity?: "success" | "error" | "warning" | "info" | "neutral",
+ /** The theme of the toast */
+ severity?: "success" | "error" | "warning" | "info" | "neutral";
}
function ToastIcon({ severity }: ToastIconProps) {
- if (severity === "success") {
- return ;
- } else if (severity === "error") {
- return ;
- } else if (severity === "warning") {
- return ;
- } else if (severity === "info") {
- return ;
- } else {
- return null;
- }
+ if (severity === "success") {
+ return (
+
+ );
+ } else if (severity === "error") {
+ return (
+
+ );
+ } else if (severity === "warning") {
+ return (
+
+ );
+ } else if (severity === "info") {
+ return (
+
+ );
+ } else {
+ return null;
+ }
}
interface ToastProps {
- /** The text to display inside the toast */
- message: string,
+ /** The text to display inside the toast */
+ message: string;
+
+ /** The theme of the toast */
+ severity?: "success" | "error" | "warning" | "info" | "neutral";
- /** The theme of the toast */
- severity?: "success" | "error" | "warning" | "info" | "neutral",
+ closeToast?: () => void;
}
function Toast({ message, severity = "neutral" }: ToastProps) {
+ // Body style
+ const body = "w-full flex py-4 pl-4 pr-6 rounded gap-2";
+
+ // Themes
+ const success = "bg-status-green-light";
+ const error = "bg-status-red-light";
+ const warning = "bg-status-yellow-light";
+ const info = "bg-status-blue-light";
+ const neutral = "bg-neutrals-light-300";
- // Body style
- const body = "flex py-2 pl-4 pr-6 rounded gap-2";
-
- // Themes
- const success = "bg-status-green-light";
- const error = "bg-status-red-light";
- const warning = "bg-status-yellow-light";
- const info = "bg-status-blue-light";
- const neutral = "bg-neutrals-light-300";
-
- return (
-
-
- { message }
-
- )
+ return (
+
+
+ {message}
+
+ );
}
-export default Toast;
\ No newline at end of file
+export default Toast;
diff --git a/src/index.css b/src/index.css
index 5ec9b1c..41f3dc5 100644
--- a/src/index.css
+++ b/src/index.css
@@ -21,6 +21,10 @@
}
@layer base {
+ .Toastify__toast {
+ background: #bbccdd;
+ }
+
.scroller {
scrollbar-color: #555770 #fffff;
scrollbar-width: auto;
diff --git a/src/routes/ImageTestRoute.tsx b/src/routes/ImageTestRoute.tsx
deleted file mode 100644
index b1fd32b..0000000
--- a/src/routes/ImageTestRoute.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import Image from "@/components/Image";
-import Overlay from '@/components/Overlay';
-import old1 from '../assets/images/old1.jpg';
-
-function ImageTestRoute() {
-
- return (
-
-
-
- );
-}
-
-export default ImageTestRoute;
\ No newline at end of file
diff --git a/src/routes/NavigationTest.tsx b/src/routes/NavigationTest.tsx
deleted file mode 100644
index 646e14f..0000000
--- a/src/routes/NavigationTest.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { NavigationBar } from "../components/NavigationBar";
-
-function NavigationTest() {
- return (
-
- {/* Using margin or padding for the parent tag can break the navigation bar. */}
-
-
- );
-}
-
-export default NavigationTest;
diff --git a/src/routes/SearchBarTestRoute.tsx b/src/routes/SearchBarTestRoute.tsx
deleted file mode 100644
index 8daeca4..0000000
--- a/src/routes/SearchBarTestRoute.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import SearchBar from "../components/SearchBar";
-
-function SearchBarTest() {
- return (
-
-
-
-
- );
-}
-
-export default SearchBarTest;
diff --git a/src/routes/SortDropdownListTestRoute.tsx b/src/routes/SortDropdownListTestRoute.tsx
deleted file mode 100644
index 6d359ea..0000000
--- a/src/routes/SortDropdownListTestRoute.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import DropdownItem from "../components/DropdownItem";
-import SortDropdownList from "../components/SortDropdownList";
-
-function SortDropdownListTestRoute() {
- return (
-
-
Hello
-
- Is this the sort dropdown list that you looking for?😩
-
-
-
-
-
What happen If I do this?
-
- );
-}
-
-export default SortDropdownListTestRoute;
diff --git a/src/routes/admin/AdminLogin.tsx b/src/routes/admin/AdminLogin.tsx
new file mode 100644
index 0000000..858cb9a
--- /dev/null
+++ b/src/routes/admin/AdminLogin.tsx
@@ -0,0 +1,79 @@
+//#region imports
+import { useState } from "react";
+import { useNavigate } from "react-router-dom";
+import { ToastContainer, toast } from "react-toastify";
+import "react-toastify/dist/ReactToastify.css";
+
+import { initializeApp } from "firebase/app";
+import { getAuth, signInWithEmailAndPassword } from "firebase/auth";
+
+import { LoginModal } from "@/components/LoginModal.js";
+import Toast from "@/components/Toast.js";
+//#endregion
+
+//#region firebase
+// Initialize Firebase
+const firebaseConfig = JSON.parse(import.meta.env.VITE_FIREBASE_CONFIG);
+const app = initializeApp(firebaseConfig);
+
+// Initialize Firebase Authentication and get a reference to the service
+const auth = getAuth(app);
+//#endregion
+
+/**
+ * Admin login page
+ * @returns Admin login page with authentication functionality
+ */
+export default function AdminLogin() {
+ const navigate = useNavigate();
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+
+ // sign in functionality
+ const signIn = () => {
+ signInWithEmailAndPassword(auth, email, password)
+ .then((userCredential) => {
+ const user = userCredential.user;
+ console.log("Signed in as: ", user.email);
+ navigate("/admin");
+ })
+ .catch((error) => {
+ console.log("Error signing in: ", error.code, error.message);
+ if (!toast.isActive("error"))
+ toast(
+ ,
+ {
+ toastId: "error",
+ style: {
+ background: "transparent",
+ boxShadow: "none",
+ },
+ },
+ );
+ });
+ };
+
+ return (
+
+
+
+
+ );
+}
diff --git a/src/routes/ButtonTestRoute.tsx b/src/routes/test/ButtonTestRoute.tsx
similarity index 100%
rename from src/routes/ButtonTestRoute.tsx
rename to src/routes/test/ButtonTestRoute.tsx
diff --git a/src/routes/ColorPickerTestRoute.tsx b/src/routes/test/ColorPickerTestRoute.tsx
similarity index 100%
rename from src/routes/ColorPickerTestRoute.tsx
rename to src/routes/test/ColorPickerTestRoute.tsx
diff --git a/src/routes/GalleryTestRoute.tsx b/src/routes/test/GalleryTestRoute.tsx
similarity index 100%
rename from src/routes/GalleryTestRoute.tsx
rename to src/routes/test/GalleryTestRoute.tsx
diff --git a/src/routes/IconOptionTest.tsx b/src/routes/test/IconOptionTest.tsx
similarity index 100%
rename from src/routes/IconOptionTest.tsx
rename to src/routes/test/IconOptionTest.tsx
diff --git a/src/routes/test/ImageTestRoute.tsx b/src/routes/test/ImageTestRoute.tsx
new file mode 100644
index 0000000..75db270
--- /dev/null
+++ b/src/routes/test/ImageTestRoute.tsx
@@ -0,0 +1,16 @@
+import Image from "@/components/Image";
+import Overlay from "@/components/Overlay";
+import old1 from "../../assets/images/old1.jpg";
+
+function ImageTestRoute() {
+ return (
+
+
+
+ );
+}
+
+export default ImageTestRoute;
diff --git a/src/routes/InputCodeTest.tsx b/src/routes/test/InputCodeTest.tsx
similarity index 100%
rename from src/routes/InputCodeTest.tsx
rename to src/routes/test/InputCodeTest.tsx
diff --git a/src/routes/InputFieldTestRoute.tsx b/src/routes/test/InputFieldTestRoute.tsx
similarity index 100%
rename from src/routes/InputFieldTestRoute.tsx
rename to src/routes/test/InputFieldTestRoute.tsx
diff --git a/src/routes/MediaUploadStatusTestRoute.tsx b/src/routes/test/MediaUploadStatusTestRoute.tsx
similarity index 100%
rename from src/routes/MediaUploadStatusTestRoute.tsx
rename to src/routes/test/MediaUploadStatusTestRoute.tsx
diff --git a/src/routes/MediaUploadZoneTestRoute.tsx b/src/routes/test/MediaUploadZoneTestRoute.tsx
similarity index 100%
rename from src/routes/MediaUploadZoneTestRoute.tsx
rename to src/routes/test/MediaUploadZoneTestRoute.tsx
diff --git a/src/routes/MemberHeaderTestRoute.tsx b/src/routes/test/MemberHeaderTestRoute.tsx
similarity index 100%
rename from src/routes/MemberHeaderTestRoute.tsx
rename to src/routes/test/MemberHeaderTestRoute.tsx
diff --git a/src/routes/MemberProfilePictureTest.tsx b/src/routes/test/MemberProfilePictureTest.tsx
similarity index 100%
rename from src/routes/MemberProfilePictureTest.tsx
rename to src/routes/test/MemberProfilePictureTest.tsx
diff --git a/src/routes/MemberTableTestRoute.tsx b/src/routes/test/MemberTableTestRoute.tsx
similarity index 100%
rename from src/routes/MemberTableTestRoute.tsx
rename to src/routes/test/MemberTableTestRoute.tsx
diff --git a/src/routes/ModalTestRoute.tsx b/src/routes/test/ModalTestRoute.tsx
similarity index 100%
rename from src/routes/ModalTestRoute.tsx
rename to src/routes/test/ModalTestRoute.tsx
diff --git a/src/routes/test/NavigationTest.tsx b/src/routes/test/NavigationTest.tsx
new file mode 100644
index 0000000..549a688
--- /dev/null
+++ b/src/routes/test/NavigationTest.tsx
@@ -0,0 +1,12 @@
+import { NavigationBar } from "../../components/NavigationBar";
+
+function NavigationTest() {
+ return (
+
+ {/* Using margin or padding for the parent tag can break the navigation bar. */}
+
+
+ );
+}
+
+export default NavigationTest;
diff --git a/src/routes/ProfilePictureTestRoute.tsx b/src/routes/test/ProfilePictureTestRoute.tsx
similarity index 100%
rename from src/routes/ProfilePictureTestRoute.tsx
rename to src/routes/test/ProfilePictureTestRoute.tsx
diff --git a/src/routes/test/SearchBarTestRoute.tsx b/src/routes/test/SearchBarTestRoute.tsx
new file mode 100644
index 0000000..e95f606
--- /dev/null
+++ b/src/routes/test/SearchBarTestRoute.tsx
@@ -0,0 +1,12 @@
+import SearchBar from "../../components/SearchBar";
+
+function SearchBarTest() {
+ return (
+
+
+
+
+ );
+}
+
+export default SearchBarTest;
diff --git a/src/routes/test/SortDropdownListTestRoute.tsx b/src/routes/test/SortDropdownListTestRoute.tsx
new file mode 100644
index 0000000..874fc13
--- /dev/null
+++ b/src/routes/test/SortDropdownListTestRoute.tsx
@@ -0,0 +1,19 @@
+import DropdownItem from "../../components/DropdownItem";
+import SortDropdownList from "../../components/SortDropdownList";
+
+function SortDropdownListTestRoute() {
+ return (
+
+
Hello
+
+ Is this the sort dropdown list that you looking for?😩
+
+
+
+
+
What happen If I do this?
+
+ );
+}
+
+export default SortDropdownListTestRoute;
diff --git a/src/routes/Test.tsx b/src/routes/test/Test.tsx
similarity index 100%
rename from src/routes/Test.tsx
rename to src/routes/test/Test.tsx
diff --git a/src/routes/ToastTestRoute.tsx b/src/routes/test/ToastTestRoute.tsx
similarity index 100%
rename from src/routes/ToastTestRoute.tsx
rename to src/routes/test/ToastTestRoute.tsx
diff --git a/src/routes/TooltipTestRoute.tsx b/src/routes/test/TooltipTestRoute.tsx
similarity index 100%
rename from src/routes/TooltipTestRoute.tsx
rename to src/routes/test/TooltipTestRoute.tsx