diff --git a/package-lock.json b/package-lock.json
index 19b0e05..be0e4cd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-checkbox": "^1.3.2",
"@radix-ui/react-collapsible": "^1.1.11",
+ "@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-select": "^2.2.5",
@@ -1282,6 +1283,42 @@
}
}
},
+ "node_modules/@radix-ui/react-dialog": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz",
+ "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.10",
+ "@radix-ui/react-focus-guards": "1.1.2",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-direction": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
diff --git a/package.json b/package.json
index 262b0fb..0cb95e6 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-checkbox": "^1.3.2",
"@radix-ui/react-collapsible": "^1.1.11",
+ "@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-select": "^2.2.5",
diff --git a/src/App.css b/src/App.css
index 1061e9b..9b68b53 100644
--- a/src/App.css
+++ b/src/App.css
@@ -125,3 +125,9 @@ body {
@apply bg-background text-foreground;
}
}
+
+@layer utilities {
+ .bg-special {
+ @apply bg-gradient-to-br from-blue-200 via-purple-200 to-pink-200;
+ }
+}
diff --git a/src/components/academic-courses-tab.tsx b/src/components/academic-courses-tab.tsx
new file mode 100644
index 0000000..73bbe23
--- /dev/null
+++ b/src/components/academic-courses-tab.tsx
@@ -0,0 +1,96 @@
+import { Button } from "./ui/button";
+import { Edit, Plus } from "lucide-react";
+import { Badge } from "@/components/ui/badge";
+import { Card, CardContent } from "./ui/card";
+import { useCoursesData } from "@/store/hooks/academics/use-courses-data";
+import { FormateDate } from "@/lib/utils";
+
+interface CourseData {
+ coursename: string;
+ professorname: string;
+ department: string;
+ status: string;
+ startdate: string;
+ enddate: string;
+}
+
+const AcademinCoursesTab = () => {
+ const { coursesInfo, error, loading } = useCoursesData();
+
+ if (loading) return
Loading courses data...
;
+ if (error) return Error loading courses data.
;
+
+ const courseData: CourseData[] = coursesInfo?.courses;
+ return (
+
+
+
Semester Management
+
+
+
+ {courseData?.map((course, index) => (
+
+
+
+
+
+
{course.coursename}
+
+ {course.status}
+
+
+
+
+ Professor:{" "}
+ {course.professorname}
+
+
+
+
+ Start Date:{" "}
+ {FormateDate(course.startdate)}
+
+
+ End Date:{" "}
+ {FormateDate(course.enddate)}
+
+
+
+
+
+ {course.status === "Planning" && (
+
+ )}
+
+
+
+
+
+ ))}
+
+
+ );
+};
+
+export default AcademinCoursesTab;
diff --git a/src/components/confirm-dialog.tsx b/src/components/confirm-dialog.tsx
new file mode 100644
index 0000000..bbd9063
--- /dev/null
+++ b/src/components/confirm-dialog.tsx
@@ -0,0 +1,69 @@
+
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+ DialogClose,
+} from "@/components/ui/dialog";
+import { Button } from "@/components/ui/button";
+import { useState, type ReactNode } from "react";
+
+interface ConfirmDialogProps {
+ title: string;
+ description: string;
+ trigger: ReactNode;
+ confirmLabel?: string;
+ cancelLabel?: string;
+ destructive?: boolean;
+ onConfirm: () => Promise | void;
+}
+
+export const ConfirmDialog = ({
+ title,
+ description,
+ trigger,
+ confirmLabel = "Confirm",
+ cancelLabel = "Cancel",
+ destructive = true,
+ onConfirm,
+}: ConfirmDialogProps) => {
+ const [open, setOpen] = useState(false);
+ const [isProcessing, setIsProcessing] = useState(false);
+
+ const handleConfirm = async () => {
+ setIsProcessing(true);
+ await onConfirm();
+ setIsProcessing(false);
+ setOpen(false);
+ };
+
+ return (
+
+ );
+};
diff --git a/src/components/dashboard-welcome.tsx b/src/components/dashboard-welcome.tsx
new file mode 100644
index 0000000..c2f4e4d
--- /dev/null
+++ b/src/components/dashboard-welcome.tsx
@@ -0,0 +1,65 @@
+import { useAdminData } from "@/store/hooks/useAdminData";
+import { AlertCircle, Verified } from "lucide-react";
+import { useEffect } from "react";
+import { Link, useNavigate } from "react-router-dom";
+import { Skeleton } from "./ui/skeleton";
+
+const DashboardWelcome = () => {
+ const { adminInfo, loading, error } = useAdminData();
+ const navigate = useNavigate();
+
+ const userInfo = adminInfo?.isUserExist;
+
+ useEffect(() => {
+ if (!loading && !userInfo) {
+ navigate("/auth/user-email");
+ }
+ }, [loading, userInfo, navigate]);
+
+ if (loading)
+ return (
+
+
+
+ );
+
+ if (error) return Error loading admin data.
;
+
+ return (
+
+
+

+
+
+
+ Welcome Back,{" "}
+
+ {userInfo?.firstname}{" "}
+ {userInfo?.isVerified && (
+
+ )}
+
+
+
+ Here's what's happening with your university today.
+
+
+
+
+ {userInfo?.isVerified === false && (
+ <>
+
+
+
Verify Account
+
+ >
+ )}
+
+
+ );
+};
+
+export default DashboardWelcome;
diff --git a/src/components/models/course-model.tsx b/src/components/models/course-model.tsx
new file mode 100644
index 0000000..690f63d
--- /dev/null
+++ b/src/components/models/course-model.tsx
@@ -0,0 +1,5 @@
+const CourseModel = () => {
+ return CourseModel
;
+};
+
+export default CourseModel;
diff --git a/src/components/setting-prefrences.tsx b/src/components/setting-prefrences.tsx
new file mode 100644
index 0000000..510c2e6
--- /dev/null
+++ b/src/components/setting-prefrences.tsx
@@ -0,0 +1,66 @@
+import { Card, CardContent } from "@/components/ui/card";
+import { Palette } from "lucide-react";
+import { Label } from "@/components/ui/label";
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select";
+import { Button } from "@/components/ui/button";
+import { useTheme } from "@/components/theme-provider";
+
+const SettingPrefrences = () => {
+ const { setTheme, theme } = useTheme();
+
+ return (
+
+
+
+
+ Preferences
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default SettingPrefrences;
diff --git a/src/components/setting-profile.tsx b/src/components/setting-profile.tsx
new file mode 100644
index 0000000..5423af0
--- /dev/null
+++ b/src/components/setting-profile.tsx
@@ -0,0 +1,218 @@
+import { Card, CardContent } from "@/components/ui/card";
+import { Camera, User } from "lucide-react";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { Textarea } from "@/components/ui/textarea";
+import { Button } from "@/components/ui/button";
+import { useState } from "react";
+import { useAdminData } from "@/store/hooks/useAdminData";
+import axios from "axios";
+import { toast } from "sonner";
+import { InputHandler } from "@/lib/utils";
+import { Skeleton } from "@/components/ui/skeleton";
+import { useRecoilRefresher_UNSTABLE } from "recoil";
+import { admin } from "@/store/atoms/admin";
+
+const base_api = import.meta.env.VITE_SERVER_BASE_URL;
+
+interface UserData {
+ firstname: string;
+ lastname: string;
+ email: string;
+ address: string;
+ bio: string;
+ dob: string;
+}
+
+const SettingProfile = () => {
+ const { adminInfo, loading, error } = useAdminData();
+ const [isLoading, setIsLoading] = useState(false);
+ const refreshAdmin = useRecoilRefresher_UNSTABLE(admin);
+
+ const [userData, setUserData] = useState({
+ firstname: "",
+ lastname: "",
+ email: "",
+ address: "",
+ bio: "",
+ dob: "",
+ });
+
+ // form handler
+
+ const handleFormSubmit = async (e: React.FormEvent) => {
+ e.preventDefault();
+ setIsLoading(true);
+
+ // removing empty fields
+ const filteredData: Partial = Object.fromEntries(
+ Object.entries(userData).filter(([_, value]) => value !== "")
+ );
+
+ try {
+ const response = await axios.put(
+ `${base_api}/api/v1/update-profile`,
+ filteredData,
+ { withCredentials: true }
+ );
+
+ if (response.status === 200) {
+ setUserData({
+ firstname: "",
+ lastname: "",
+ email: "",
+ address: "",
+ bio: "",
+ dob: "",
+ });
+ toast.success("Profile updated successfully");
+ setIsLoading(false);
+ refreshAdmin();
+ }
+ } catch (error) {
+ console.log(error);
+ setIsLoading(false);
+ }
+ };
+
+ const userInfo = adminInfo?.isUserExist;
+
+ if (loading) {
+ return (
+
+
+ {/* Skeleton Avatar */}
+
+
+
+
+
+
+ {/* Skeleton Form Fields */}
+
+ {Array.from({ length: 4 }).map((_, index) => (
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
+ if (error) return Error loading admin data.
;
+
+ return (
+
+
+ {/* Profile Photo */}
+
+
+ {loading ? (
+
+ ) : (
+

+ )}
+
+
+
+ JPG, PNG or GIF. Max size 2MB.
+
+
+
+ {/* Personal Information */}
+
+
+
+ );
+};
+
+export default SettingProfile;
diff --git a/src/components/setting-security.tsx b/src/components/setting-security.tsx
new file mode 100644
index 0000000..6cf3ad8
--- /dev/null
+++ b/src/components/setting-security.tsx
@@ -0,0 +1,136 @@
+import { useState } from "react";
+import { Card, CardContent } from "./ui/card";
+import { CircleAlert, Shield } from "lucide-react";
+import { Label } from "@radix-ui/react-label";
+import { Input } from "./ui/input";
+import { Button } from "./ui/button";
+import axios from "axios";
+import { toast } from "sonner";
+import { ConfirmDialog } from "./confirm-dialog";
+import { useNavigate } from "react-router";
+
+const base_api = import.meta.env.VITE_SERVER_BASE_URL;
+
+const SettingSecurity = () => {
+ const [password, setPassword] = useState("");
+ const [confirmPassword, setConfirmPassword] = useState("");
+
+ const [isLoading, setIsLoading] = useState(false);
+ const navigate = useNavigate();
+
+ const handleFormSubmit = async (e: React.FormEvent) => {
+ e.preventDefault();
+ setIsLoading(true);
+
+ try {
+ const response = await axios.put(
+ `${base_api}/api/v1/update-password`,
+ { password },
+ { withCredentials: true }
+ );
+
+ if (response.status === 200) {
+ setPassword("");
+ setConfirmPassword("");
+ toast.success("password updated successfully");
+ setIsLoading(false);
+ }
+ } catch (error) {
+ console.log(error);
+ setIsLoading(false);
+ }
+ };
+
+ // delete account
+ const handleDelete = async () => {
+ try {
+ const response = await axios.delete(`${base_api}/api/v1/delete-profile`, {
+ withCredentials: true,
+ });
+
+ if (response.status === 200) {
+ setPassword("");
+ toast.success("acount deleted !!");
+ setIsLoading(false);
+ navigate("/auth/sign-up");
+ }
+ } catch (error) {
+ console.log(error);
+ setIsLoading(false);
+ }
+ };
+
+ const isMatch =
+ password !== "" && confirmPassword !== "" && password === confirmPassword;
+
+ return (
+
+
+
+
+
+ Security
+
+
+
+
+
+
+
+
+
+
+ Danger Zone
+
+
+ Delete Account
+
+ }
+ />
+
+
+
+ );
+};
+
+export default SettingSecurity;
diff --git a/src/components/sidebar.tsx b/src/components/sidebar.tsx
index e3edd10..afc946d 100644
--- a/src/components/sidebar.tsx
+++ b/src/components/sidebar.tsx
@@ -11,9 +11,20 @@ import {
GraduationCap,
Calendar,
Megaphone,
+ UtensilsCrossed,
+ BookOpen,
+ Briefcase,
+ UserCheck,
+ MapPin,
+ ChevronDown,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { Link, useLocation } from "react-router-dom";
+import {
+ Collapsible,
+ CollapsibleTrigger,
+ CollapsibleContent,
+} from "@/components/ui/collapsible";
interface SidebarItem {
icon: React.ComponentType<{ className?: string }>;
@@ -67,6 +78,45 @@ const sidebarItems: SidebarItem[] = [
},
];
+const studentPortalItems: SidebarItem[] = [
+ {
+ icon: UtensilsCrossed,
+ label: "Restaurant",
+ id: "student-pages-restaurant",
+ href: "/restaurant",
+ },
+ {
+ icon: BookOpen,
+ label: "Library",
+ id: "student-pages-library",
+ href: "/library",
+ },
+ {
+ icon: UserCheck,
+ label: "Fresh Man",
+ id: "student-pages-services",
+ href: "/Freshman",
+ },
+ {
+ icon: Briefcase,
+ label: "Services",
+ id: "student-pages-services",
+ href: "/services",
+ },
+ {
+ icon: Users,
+ label: "Academic Personnel",
+ id: "student-pages-faculty",
+ href: "/faculty",
+ },
+ {
+ icon: MapPin,
+ label: "Campus Map",
+ id: "student-pages-campus",
+ href: "/campus-map",
+ },
+];
+
interface AdminPortalSidebarProps {
onItemSelect: (id: string) => void;
}
@@ -77,6 +127,7 @@ export const AdminPortalSidebar = ({
const location = useLocation();
const [isMobileOpen, setIsMobileOpen] = useState(false);
const [isDesktopCollapsed, setIsDesktopCollapsed] = useState(false);
+ const [isStudentPortalOpen, setIsStudentPortalOpen] = useState(false);
const currentPath = location.pathname;
const activeItem = sidebarItems.find((item) => item.href === currentPath)?.id;
@@ -184,6 +235,59 @@ export const AdminPortalSidebar = ({
);
})}
+
+
+
+
+
+ {(!isDesktopCollapsed || isMobileOpen) && (
+
+ {studentPortalItems.map((item) => (
+ {
+ onItemSelect(item.id);
+ setIsMobileOpen(false);
+ }}
+ to={item.href}
+ className={`
+ w-full flex items-center gap-3 p-2 rounded-lg text-left transition-colors text-sm
+ ${
+ activeItem === item.id
+ ? "bg-primary text-primary-foreground"
+ : "text-muted-foreground hover:text-foreground hover:bg-muted"
+ }
+ `}
+ >
+
+ {item.label}
+
+ ))}
+
+ )}
+
diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx
new file mode 100644
index 0000000..6cb123b
--- /dev/null
+++ b/src/components/ui/dialog.tsx
@@ -0,0 +1,141 @@
+import * as React from "react"
+import * as DialogPrimitive from "@radix-ui/react-dialog"
+import { XIcon } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+function Dialog({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function DialogTrigger({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function DialogPortal({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function DialogClose({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function DialogOverlay({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DialogContent({
+ className,
+ children,
+ showCloseButton = true,
+ ...props
+}: React.ComponentProps & {
+ showCloseButton?: boolean
+}) {
+ return (
+
+
+
+ {children}
+ {showCloseButton && (
+
+
+ Close
+
+ )}
+
+
+ )
+}
+
+function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function DialogTitle({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DialogDescription({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+export {
+ Dialog,
+ DialogClose,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogOverlay,
+ DialogPortal,
+ DialogTitle,
+ DialogTrigger,
+}
diff --git a/src/components/ui/skeleton.tsx b/src/components/ui/skeleton.tsx
new file mode 100644
index 0000000..32ea0ef
--- /dev/null
+++ b/src/components/ui/skeleton.tsx
@@ -0,0 +1,13 @@
+import { cn } from "@/lib/utils"
+
+function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+export { Skeleton }
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index 58ce603..7865282 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -22,3 +22,9 @@ export function InputHandler(
export function handleVisibleToggle(setState: any) {
setState((prev: any) => !prev);
}
+
+// date formator
+
+export function FormateDate(date: any) {
+ return new Date(date).toLocaleDateString("en-CA");
+}
diff --git a/src/pages/auth/layout.tsx b/src/pages/auth/layout.tsx
index f4c3e26..ce85306 100644
--- a/src/pages/auth/layout.tsx
+++ b/src/pages/auth/layout.tsx
@@ -4,7 +4,7 @@ import { Outlet } from "react-router-dom";
const AuthLayout = () => {
return (
-
+
Welcome To Place Where Possibilities Begin
diff --git a/src/pages/dashboard/academic.tsx b/src/pages/dashboard/academic.tsx
index 9bf084d..c98eafa 100644
--- a/src/pages/dashboard/academic.tsx
+++ b/src/pages/dashboard/academic.tsx
@@ -3,16 +3,9 @@ import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { useCoursesData } from "@/store/hooks/academics/use-courses-data";
+import AcademinCoursesTab from "@/components/academic-courses-tab";
+import ErrorBoundary from "@/components/error-boundary";
-interface courceData {
- name: string;
- professor: string;
- department: string;
- status: string;
- startDate: string;
- endDate: string;
-}
interface DepartmentData {
name: string;
school: string;
@@ -36,40 +29,6 @@ interface semesterData {
status: string;
}
-const courceData: courceData[] = [
- {
- name: "Data-base system",
- professor: "Dr. John dow",
- department: "School of Engineering",
- status: "Planning",
- startDate: "2024-09-15",
- endDate: "2024-12-20",
- },
- {
- name: "Data-base system",
- professor: "Dr. John dow",
- department: "School of Engineering",
- status: "scheduled",
- startDate: "2024-09-15",
- endDate: "2024-12-20",
- },
- {
- name: "Data-base system",
- professor: "Dr. John dow",
- department: "School of Engineering",
- status: "cancled",
- startDate: "2024-09-15",
- endDate: "2024-12-20",
- },
- {
- name: "Data-base system",
- professor: "Dr. John dow",
- department: "School of Engineering",
- status: "scheduled",
- startDate: "2024-09-15",
- endDate: "2024-12-20",
- },
-];
const departmentData: DepartmentData[] = [
{
name: "Computer Science",
@@ -148,15 +107,6 @@ const semesterData: semesterData[] = [
];
const Academic = () => {
- const { coursesInfo, error, loading } = useCoursesData();
-
- if (loading) return
Loading admin data...
;
- if (error) return Error loading admin data.
;
-
- const courseData = coursesInfo.isUserExist;
-
- console.log(courseData);
-
return (
{/* Header */}
@@ -247,73 +197,9 @@ const Academic = () => {
-
-
Semester Management
-
-
-
-
- {courceData.map((course, index) => (
-
-
-
-
-
-
{course.name}
-
- {course.status}
-
-
-
-
- Professor:{" "}
- {course.professor}
-
-
-
-
- Start Date:{" "}
- {course.startDate}
-
-
- End Date:{" "}
- {course.endDate}
-
-
-
-
-
- {course.status === "Planning" && (
-
- )}
-
-
-
-
-
- ))}
-
+
+
+
diff --git a/src/pages/dashboard/dashboard.tsx b/src/pages/dashboard/dashboard.tsx
index 3845ddc..23dfa64 100644
--- a/src/pages/dashboard/dashboard.tsx
+++ b/src/pages/dashboard/dashboard.tsx
@@ -5,17 +5,13 @@ import {
BarChart3,
Shield,
Settings,
- User,
- AlertCircle,
- Verified,
} from "lucide-react";
import { ServiceCard } from "@/components/service-card";
import { Help } from "@/components/help";
import { TodaysHighlights } from "@/components/todays-highlights";
import { SystemOverview } from "@/components/system-overview";
import ErrorBoundary from "@/components/error-boundary";
-import { useAdminData } from "../../store/hooks/useAdminData";
-import { Link, useNavigate } from "react-router-dom";
+import DashboardWelcome from "@/components/dashboard-welcome";
interface AdminService {
icon: React.ComponentType<{ className?: string }>;
@@ -71,55 +67,12 @@ const adminServiceCards: AdminService[] = [
];
export const AdminDashboard = () => {
- const { adminInfo, loading, error } = useAdminData();
- const navigate = useNavigate();
-
- const userInfo = adminInfo?.isUserExist;
-
- if (loading) return Loading admin data...
;
- if (error) return Error loading admin data.
;
-
- if (!userInfo) {
- navigate("/auth/user-email");
- }
-
return (
<>
{/* Header */}
-
-
- {loading ? (
-
- ) : (
-

- )}
-
-
-
- Welcome Back,{" "}
- {loading ? (
- "User "
- ) : (
-
- {userInfo?.firstname}
-
- )}
-
-
- Here's what's happening with your university today.
-
-
-
-
-
+
+
+
{/* Services Grid */}
diff --git a/src/pages/dashboard/setting.tsx b/src/pages/dashboard/setting.tsx
index 49137ad..4016522 100644
--- a/src/pages/dashboard/setting.tsx
+++ b/src/pages/dashboard/setting.tsx
@@ -1,95 +1,11 @@
-import { Button } from "@/components/ui/button";
-import { Card, CardContent } from "@/components/ui/card";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select";
+import ErrorBoundary from "@/components/error-boundary";
+import SettingPrefrences from "@/components/setting-prefrences";
+import SettingProfile from "@/components/setting-profile";
+import SettingSecurity from "@/components/setting-security";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { Textarea } from "@/components/ui/textarea";
-import { handleVisibleToggle, InputHandler } from "@/lib/utils";
-import { useAdminData } from "@/store/hooks/useAdminData";
-import axios from "axios";
-import {
- User,
- Shield,
- Camera,
- Palette,
- EyeOff,
- Eye,
- CircleAlert,
-} from "lucide-react";
-import { useState } from "react";
-import { toast } from "sonner";
-
-interface UserData {
- firstname: string;
- lastname: string;
- email: string;
- address: string;
- bio: string;
- dob: string;
-}
-
-const base_api = import.meta.env.VITE_SERVER_BASE_URL;
+import { User, Shield, Palette } from "lucide-react";
const Setting = () => {
- const { adminInfo, loading, error } = useAdminData();
- const [showPassword, setShowPassword] = useState
(true);
- const [isLoading, setIsLoading] = useState(false);
-
- const [userData, setUserData] = useState({
- firstname: "",
- lastname: "",
- email: "",
- address: "",
- bio: "",
- dob: "",
- });
-
- // update data
-
- const handleFormSubmit = async (e: React.FormEvent) => {
- e.preventDefault();
- setIsLoading(true);
-
- // removing empty fields
- const filteredData: Partial = Object.fromEntries(
- Object.entries(userData).filter(([_, value]) => value !== "")
- );
-
- try {
- const response = await axios.put(
- `${base_api}/api/v1/update-profile`,
- filteredData,
- { withCredentials: true }
- );
-
- if (response.status === 200) {
- setUserData({
- firstname: "",
- lastname: "",
- email: "",
- address: "",
- bio: "",
- dob: "",
- });
- toast.success("Profile updated successfully");
- setIsLoading(false);
- }
- } catch (error) {
- console.log(error);
- setIsLoading(false);
- }
- };
-
- const userInfo = adminInfo?.isUserExist;
- if (loading) return Loading admin data...
;
- if (error) return Error loading admin data.
;
return (
{/* Header */}
@@ -101,7 +17,7 @@ const Setting = () => {
{/* Settings Tabs */}
-
+
@@ -118,255 +34,21 @@ const Setting = () => {
-
-
- {/* Profile Photo */}
-
-
- {loading ? (
-
- ) : (
-

- )}
-
-
-
- JPG, PNG or GIF. Max size 2MB.
-
-
-
- {/* Personal Information */}
-
-
-
+
+
+
-
-
-
-
- Preferences
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
- Security
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Danger Zone
-
-
-
-
-
-
+
+
+
diff --git a/src/routes/index.tsx b/src/routes/index.tsx
index 3dbfd79..e90e8ff 100644
--- a/src/routes/index.tsx
+++ b/src/routes/index.tsx
@@ -34,7 +34,6 @@ const Paths = () => {
{/* dashboard */}
-
}>
} />
} />