diff --git a/components.json b/components.json
new file mode 100644
index 0000000..0e8b633
--- /dev/null
+++ b/components.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "new-york",
+ "rsc": true,
+ "tsx": true,
+ "tailwind": {
+ "config": "tailwind.config.ts",
+ "css": "src/app/globals.css",
+ "baseColor": "neutral",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ },
+ "iconLibrary": "lucide"
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index e801e52..6fac074 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,10 +8,17 @@
"name": "leadlly.admin.web.next",
"version": "0.1.0",
"dependencies": {
+ "@next/font": "^14.2.15",
+ "@radix-ui/react-progress": "^1.1.2",
+ "@radix-ui/react-slot": "^1.1.2",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.477.0",
"next": "15.0.3",
"react": "19.0.0-rc-66855b96-20241106",
"react-dom": "19.0.0-rc-66855b96-20241106",
- "tailwind-merge": "^2.3.0",
+ "react-icons": "^5.5.0",
+ "tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7"
},
"devDependencies": {
@@ -477,6 +484,15 @@
"integrity": "sha512-t9Xy32pjNOvVn2AS+Utt6VmyrshbpfUMhIjFO60gI58deSo/KgLOp31XZ4O+kY/Is8WAGYwA5gR7kOb1eORDBA==",
"license": "MIT"
},
+ "node_modules/@next/font": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/font/-/font-14.2.15.tgz",
+ "integrity": "sha512-QopYhBmCDDrNDynbi+ZD1hDZXmQXVFo7TmAFp4DQgO/kogz1OLbQ92hPigJbj572eZ3GaaVxNIyYVn3/eAsehg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "next": "*"
+ }
+ },
"node_modules/@next/swc-darwin-arm64": {
"version": "15.0.3",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.3.tgz",
@@ -650,6 +666,101 @@
"node": ">=14"
}
},
+ "node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
+ "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz",
+ "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz",
+ "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.1.2"
+ },
+ "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-progress": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.2.tgz",
+ "integrity": "sha512-u1IgJFQ4zNAUTjGdDL5dcl/U8ntOR6jsnhxKb5RKp5Ozwl88xKR9EqRZOe/Mk8tnx0x5tNUe2F+MzsyjqMg0MA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.2"
+ },
+ "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-slot": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz",
+ "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@swc/counter": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
@@ -679,14 +790,14 @@
"version": "15.7.13",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
"integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/@types/react": {
"version": "18.3.12",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz",
"integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
@@ -697,7 +808,7 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"@types/react": "*"
@@ -867,12 +978,33 @@
"node": ">= 6"
}
},
+ "node_modules/class-variance-authority": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "clsx": "^2.1.1"
+ },
+ "funding": {
+ "url": "https://polar.sh/cva"
+ }
+ },
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
"license": "MIT"
},
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
@@ -955,7 +1087,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/detect-libc": {
@@ -1248,6 +1380,15 @@
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
},
+ "node_modules/lucide-react": {
+ "version": "0.477.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.477.0.tgz",
+ "integrity": "sha512-yCf7aYxerFZAbd8jHJxjwe1j7jEMPptjnaOqdYeirFnEy85cNR3/L+o0I875CYFYya+eEVzZSbNuRk8BZPDpVw==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -1701,6 +1842,15 @@
"react": "19.0.0-rc-66855b96-20241106"
}
},
+ "node_modules/react-icons": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
+ "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -2045,9 +2195,9 @@
}
},
"node_modules/tailwind-merge": {
- "version": "2.5.4",
- "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz",
- "integrity": "sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz",
+ "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==",
"license": "MIT",
"funding": {
"type": "github",
diff --git a/package.json b/package.json
index b2efd97..8de3b1a 100644
--- a/package.json
+++ b/package.json
@@ -9,18 +9,25 @@
"lint": "next lint"
},
"dependencies": {
+ "@next/font": "^14.2.15",
+ "@radix-ui/react-progress": "^1.1.2",
+ "@radix-ui/react-slot": "^1.1.2",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.477.0",
+ "next": "15.0.3",
"react": "19.0.0-rc-66855b96-20241106",
"react-dom": "19.0.0-rc-66855b96-20241106",
- "next": "15.0.3",
- "tailwind-merge": "^2.3.0",
+ "react-icons": "^5.5.0",
+ "tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7"
},
"devDependencies": {
- "typescript": "^5",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"postcss": "^8",
- "tailwindcss": "^3.4.1"
+ "tailwindcss": "^3.4.1",
+ "typescript": "^5"
}
}
diff --git a/public/student-ppf.png b/public/student-ppf.png
new file mode 100644
index 0000000..7394f76
Binary files /dev/null and b/public/student-ppf.png differ
diff --git a/public/university-logo.png b/public/university-logo.png
new file mode 100644
index 0000000..71556e2
Binary files /dev/null and b/public/university-logo.png differ
diff --git a/public/user-logo.png b/public/user-logo.png
new file mode 100644
index 0000000..3ebc317
Binary files /dev/null and b/public/user-logo.png differ
diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx
index 45e3e9d..c38d225 100644
--- a/src/app/(auth)/login/page.tsx
+++ b/src/app/(auth)/login/page.tsx
@@ -1,9 +1,70 @@
-import React from 'react'
+import Link from "next/link";
+import React from "react";
+import { FaGoogle } from "react-icons/fa";
const Login = () => {
return (
-
Login
- )
-}
+
+
+
+ Welcome Back
+
-export default Login
\ No newline at end of file
+ {/* Email & Password Form */}
+
+
+ {/* Divider */}
+
+
+ {/* Google Login */}
+
+
+ Sign in with Google
+
+
+ {/* Footer */}
+
+ Don't have an account?{" "}
+
+ Sign up
+
+
+
+
+ );
+};
+
+export default Login;
diff --git a/src/app/(root)/(dashboard)/_components/header.tsx b/src/app/(root)/(dashboard)/_components/header.tsx
new file mode 100644
index 0000000..c2d368e
--- /dev/null
+++ b/src/app/(root)/(dashboard)/_components/header.tsx
@@ -0,0 +1,44 @@
+import { Button } from "@/components/ui/button";
+import React from "react";
+
+const Header = () => {
+ return (
+
+
+ Institute Overview & Management
+
+
+
+
+
+
+
+
+ Edit
+
+
+ );
+};
+
+export default Header;
diff --git a/src/app/(root)/(dashboard)/_components/index.ts b/src/app/(root)/(dashboard)/_components/index.ts
deleted file mode 100644
index 28d4d61..0000000
--- a/src/app/(root)/(dashboard)/_components/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-// here we can add all the components that we want to use in the dashboard (you can rename this file to whatever you want)
\ No newline at end of file
diff --git a/src/app/(root)/(dashboard)/_components/instituteOverview.tsx b/src/app/(root)/(dashboard)/_components/instituteOverview.tsx
new file mode 100644
index 0000000..a4535d0
--- /dev/null
+++ b/src/app/(root)/(dashboard)/_components/instituteOverview.tsx
@@ -0,0 +1,87 @@
+import React from "react";
+import Image from "next/image";
+
+const InstituteOverview = () => {
+ return (
+
+
+
+
+
+
+
+
Established in 2001
+
+ Chaitanya Bharathi Institute
+
+
+ Institute Code:{" "}
+ 21XYZ1234
+
+
+
+
+
+
+
+
+
+
Address:
+
+ 123, Main Street, City, Country
+
+
+
+
+
+
+
+
+
+
Contact:
+ +1234567890
+
+
+
+
+
+
+
+
+
+
Email:
+ info@institute.com
+
+
+
+
+
+ );
+};
+
+export default InstituteOverview;
diff --git a/src/app/(root)/(dashboard)/_components/studentsOverview.tsx b/src/app/(root)/(dashboard)/_components/studentsOverview.tsx
new file mode 100644
index 0000000..cb71b42
--- /dev/null
+++ b/src/app/(root)/(dashboard)/_components/studentsOverview.tsx
@@ -0,0 +1,135 @@
+import React from "react";
+import Link from "next/link";
+import Image from "next/image";
+
+interface StudentsOverviewProps {
+ totalStudents: number;
+ activeCourses: number;
+ averageAttendance: number;
+ performanceIndex: number;
+}
+
+const StudentsOverview = () => {
+ return (
+
+
Students Overview
+
+
+
+
+
📚
+ View Students
+
+
+ );
+};
+
+export default StudentsOverview;
diff --git a/src/app/(root)/(dashboard)/_components/teacherOverview.tsx b/src/app/(root)/(dashboard)/_components/teacherOverview.tsx
new file mode 100644
index 0000000..0258469
--- /dev/null
+++ b/src/app/(root)/(dashboard)/_components/teacherOverview.tsx
@@ -0,0 +1,121 @@
+import React from "react";
+import Link from "next/link";
+
+interface TeachersOverviewProps {
+ totalTeachers: number;
+ departments: number;
+ activeClasses: number;
+ satisfactionRate: number;
+}
+
+const TeachersOverview = () => {
+ return (
+
+
Teachers Overview
+
+
+
+
+
🎓
+ View Teachers
+
+
+ );
+};
+
+export default TeachersOverview;
diff --git a/src/app/(root)/(dashboard)/page.tsx b/src/app/(root)/(dashboard)/page.tsx
index 75a3155..93f0fe3 100644
--- a/src/app/(root)/(dashboard)/page.tsx
+++ b/src/app/(root)/(dashboard)/page.tsx
@@ -1,7 +1,22 @@
-import Image from "next/image";
+import InstituteOverview from "./_components/instituteOverview";
+import StudentsOverview from "./_components/studentsOverview";
+import TeachersOverview from "./_components/teacherOverview";
+import Header from "./_components/header";
-export default function Home() {
+export default function DashboardPage() {
return (
- <>Home>
+
+ {/* Header Section */}
+
+
+ {/* Institute Overview */}
+
+
+ {/* Student & Teacher Overview Section */}
+
+
+
+
+
);
}
diff --git a/src/app/(root)/batches/[batchId]/students/components/loading.tsx b/src/app/(root)/batches/[batchId]/students/components/loading.tsx
new file mode 100644
index 0000000..ad42c87
--- /dev/null
+++ b/src/app/(root)/batches/[batchId]/students/components/loading.tsx
@@ -0,0 +1,12 @@
+import React from 'react'
+
+const Loading = () => {
+ return (
+
+
Fetching students...
+
+
+ )
+}
+
+export default Loading
diff --git a/src/app/(root)/batches/[batchId]/students/components/studentsData.tsx b/src/app/(root)/batches/[batchId]/students/components/studentsData.tsx
new file mode 100644
index 0000000..cb82790
--- /dev/null
+++ b/src/app/(root)/batches/[batchId]/students/components/studentsData.tsx
@@ -0,0 +1,69 @@
+import { Card, CardContent } from '@/components/ui/card';
+import { Progress } from '@/components/ui/progress';
+import { Student } from '@/types/students';
+import Image from 'next/image';
+import React from 'react'
+
+const StudentsData = ({studentsData, filter} : {studentsData:Student[], filter: string}) => {
+ return (
+
+ {studentsData
+ .filter((student) => filter === "all" || student.status === filter)
+ .map((student, index) => {
+ const statusColors: Record
= {
+ excellent: "bg-[#00FF132E]",
+ optimal: "bg-[#FFF2D5]",
+ inefficient: "bg-[#FFDBDA]",
+ };
+
+ const progressColors: Record = {
+ excellent: "bg-green-500",
+ optimal: "bg-orange-500",
+ inefficient: "bg-red-500",
+ };
+
+ return (
+
+
+
+
+
+ 😜
+
+
+
+
{student.name}
+
+ Class: {student.class}
+
+
+
+
+
+ );
+ })}
+
+ )
+}
+
+export default StudentsData
diff --git a/src/app/(root)/batches/[batchId]/students/page.tsx b/src/app/(root)/batches/[batchId]/students/page.tsx
new file mode 100644
index 0000000..6c8eecc
--- /dev/null
+++ b/src/app/(root)/batches/[batchId]/students/page.tsx
@@ -0,0 +1,178 @@
+"use client";
+
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { options, Student } from "@/types/students";
+import Image from "next/image";
+import { useParams } from "next/navigation";
+import { useEffect, useState } from "react";
+import StudentsData from "./components/studentsData";
+import Loading from "./components/loading";
+
+export default function StudentsInfo() {
+ const [filter, setFilter] = useState("all");
+ const [studentsData, setStudentsData] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const params = useParams();
+
+ const batchId = params?.batchId as string;
+
+ const fetchStudents = async (batchId: string) => {
+ try {
+ const response = await fetch(`/api/batches/${batchId}/students`);
+ if (!response.ok) {
+ throw new Error("Failed to fetch students");
+ }
+ const data = await response.json();
+ return data.students;
+ } catch (error) {
+ console.error("Error fetching students:", error);
+ return [];
+ }
+ };
+
+ useEffect(() => {
+ if (!batchId) return;
+
+ const getStudents = async () => {
+ setLoading(true);
+ const data = await fetchStudents(batchId);
+ setStudentsData(data);
+ setLoading(false);
+ };
+
+ getStudents();
+ }, [batchId]);
+
+ return (
+
+
+
+
+
+
+
+ {options.map((option) => (
+
setFilter(option)}
+ >
+ {option.charAt(0).toUpperCase() + option.slice(1)}
+
+ ))}
+
+
+
+
+
+
+ {loading ? (
+
+ ) : (
+
+ )}
+
+ );
+}
diff --git a/src/app/(root)/batches/components/batches.tsx b/src/app/(root)/batches/components/batches.tsx
new file mode 100644
index 0000000..7527922
--- /dev/null
+++ b/src/app/(root)/batches/components/batches.tsx
@@ -0,0 +1,282 @@
+import { BatchesData } from "@/types/batches";
+import Link from "next/link";
+import React from "react";
+
+interface BatchesProps {
+ batchesData: BatchesData;
+}
+
+const Batches: React.FC = ({ batchesData }) => {
+ return (
+
+ {batchesData.standards.map((standard, index) => (
+
+
+
{standard.name}
+
+
+
+
+ Add batch
+
+
+
+ {!standard?.batches || standard.batches.length === 0 ? (
+ // Loading spinner when data is unavailable
+
+ ) : (
+
+ {standard.batches.map((batch) => (
+
+
+
+ {batch.name === "Omega" ? (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ) : batch.name === "Sigma" ? (
+
+
+
+
+ ) : (
+
+
+
+
+
+
+
+ )}
+
+
+
+ {batch.name}
+
+
{batch.standard}
+
+
+ Active
+
+
+
+
+
+
+ Subject:{" "}
+
+ {batch.subjects.join(", ")}
+
+
+
+ Total Students:{" "}
+
+ {batch.totalStudents}
+
+
+
+
+
+ {batch.totalStudents}/{batch.maxStudents}
+
+
+
+
+
+
+ ))}
+
+ )}
+
+ ))}
+
+ );
+};
+
+export default Batches;
diff --git a/src/app/(root)/batches/components/filter.tsx b/src/app/(root)/batches/components/filter.tsx
new file mode 100644
index 0000000..e7d9e43
--- /dev/null
+++ b/src/app/(root)/batches/components/filter.tsx
@@ -0,0 +1,75 @@
+import { BatchFilters } from '@/types/batches'
+import React from 'react'
+
+type FilterBatchesProps = {
+ filters: BatchFilters;
+ handleFilterChange: (e: React.ChangeEvent) => void;
+ };
+
+const FilterBatches = ({ filters, handleFilterChange }: FilterBatchesProps) => {
+ return (
+
+
+
+
+
+
+
+ Filter by :
+
+
+
+
+
+ All Standards
+ 11th Standard
+ 12th Standard
+
+
+
+ All Subjects
+ Physics
+ Chemistry
+ Biology
+ Mathematics
+
+
+
+ All Teachers
+ Dr. Sarah Wilson
+
+
+
+
+ )
+}
+
+export default FilterBatches
diff --git a/src/app/(root)/batches/components/loading.tsx b/src/app/(root)/batches/components/loading.tsx
new file mode 100644
index 0000000..bacc86f
--- /dev/null
+++ b/src/app/(root)/batches/components/loading.tsx
@@ -0,0 +1,29 @@
+import React from 'react'
+
+const Loading = () => {
+ return (
+
+ )
+}
+
+export default Loading
diff --git a/src/app/(root)/batches/page.tsx b/src/app/(root)/batches/page.tsx
new file mode 100644
index 0000000..d77e3a3
--- /dev/null
+++ b/src/app/(root)/batches/page.tsx
@@ -0,0 +1,73 @@
+"use client";
+
+import React, { useState, useEffect } from "react";
+import FilterBatches from "./components/filter";
+import Loading from "./components/loading";
+import Batches from "./components/batches";
+import { BatchesData, BatchFilters } from "@/types/batches";
+
+export default function BatchesPage() {
+ const [batchesData, setBatchesData] = useState(null);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+ const [filters, setFilters] = useState({
+ standard: "",
+ subject: "",
+ teacher: "",
+ });
+
+ const buildQueryParams = () => {
+ const queryParams = new URLSearchParams();
+ Object.entries(filters).forEach(([key, value]) => {
+ if (value) queryParams.append(key, value);
+ });
+ return queryParams.toString();
+ };
+
+ // Fetch batches data
+ const fetchBatches = async () => {
+ try {
+ setLoading(true);
+ const response = await fetch(`/api/batches?${buildQueryParams()}`);
+
+ if (!response.ok) throw new Error("Failed to fetch batches");
+
+ const data = await response.json();
+ setBatchesData(data);
+ setError(null);
+ } catch (err) {
+ setError("Error loading batches. Please try again later.");
+ console.error("Error fetching batches:", err);
+ } finally {
+ setTimeout(() => setLoading(false), 200);
+ }
+ };
+
+ useEffect(() => {
+ fetchBatches();
+ }, [filters]);
+
+ const handleFilterChange = (e: React.ChangeEvent) => {
+ setFilters((prev) => ({ ...prev, [e.target.name]: e.target.value }));
+ };
+
+ return (
+
+
Student Batches of Institute
+
+
+ {loading &&
}
+ {error &&
{error}
}
+ {batchesData && !loading && batchesData.standards.length > 0 ? (
+
+ ) : (
+ !loading &&
+ !error && (
+
+
No batches found. Try adjusting your filters.
+
+ )
+ )}
+
+ );
+}
diff --git a/src/app/(root)/teacher/[teacherId]/_components/index.ts b/src/app/(root)/teacher/[teacherId]/_components/index.ts
deleted file mode 100644
index 28d4d61..0000000
--- a/src/app/(root)/teacher/[teacherId]/_components/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-// here we can add all the components that we want to use in the dashboard (you can rename this file to whatever you want)
\ No newline at end of file
diff --git a/src/app/(root)/teacher/[teacherId]/page.tsx b/src/app/(root)/teacher/[teacherId]/page.tsx
deleted file mode 100644
index 3017769..0000000
--- a/src/app/(root)/teacher/[teacherId]/page.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import React from 'react'
-
-const TeacherPage = () => {
- return (
- TeacherPage
- )
-}
-
-export default TeacherPage
\ No newline at end of file
diff --git a/src/app/api/batches/[batchId]/students/route.ts b/src/app/api/batches/[batchId]/students/route.ts
new file mode 100644
index 0000000..2e0feb2
--- /dev/null
+++ b/src/app/api/batches/[batchId]/students/route.ts
@@ -0,0 +1,38 @@
+import { NextRequest, NextResponse } from 'next/server';
+
+// Mock data for students
+const getStudentsData = (batchId: string) => {
+ return {
+ students: [
+ { name: "Abhinav Mishra", class: 11, level: 80, status: "excellent" },
+ { name: "Abhinav Mishra", class: 11, level: 50, status: "optimal" },
+ { name: "Abhinav Mishra", class: 11, level: 20, status: "inefficient" },
+ { name: "Abhinav Mishra", class: 11, level: 80, status: "excellent" },
+ { name: "Abhinav Mishra", class: 11, level: 30, status: "inefficient" },
+ { name: "Abhinav Mishra", class: 11, level: 50, status: "optimal" },
+ { name: "Abhinav Mishra", class: 11, level: 40, status: "optimal" },
+ { name: "Abhinav Mishra", class: 11, level: 90, status: "excellent" },
+ { name: "Abhinav Mishra", class: 11, level: 30, status: "inefficient" },
+ { name: "Abhinav Mishra", class: 11, level: 20, status: "inefficient" },
+ { name: "Abhinav Mishra", class: 11, level: 40, status: "optimal" },
+ { name: "Abhinav Mishra", class: 11, level: 90, status: "excellent" },
+ ]
+ };
+};
+
+export async function GET(
+ request: NextRequest,
+ { params }: { params: { batchId: string } }
+) {
+ const batchId = params.batchId;
+ if (!batchId) {
+ return NextResponse.json({ error: 'Batch ID is required' }, { status: 400 });
+ }
+
+ try {
+ const data = getStudentsData(batchId);
+ return NextResponse.json(data, { status: 200 });
+ } catch (error) {
+ return NextResponse.json({ error: 'Failed to fetch students' }, { status: 500 });
+ }
+}
diff --git a/src/app/api/batches/route.ts b/src/app/api/batches/route.ts
new file mode 100644
index 0000000..621b4fe
--- /dev/null
+++ b/src/app/api/batches/route.ts
@@ -0,0 +1,123 @@
+import { NextRequest, NextResponse } from 'next/server';
+
+// Mock data for batches - in a real app, this would come from a database
+const batchesData = {
+ standards: [
+ {
+ name: "11th standard",
+ batches: [
+ {
+ id: "11-omega-1",
+ name: "Omega",
+ standard: "11th Class",
+ subjects: ["Chemistry", "Physics", "Biology"],
+ totalStudents: 120,
+ maxStudents: 180,
+ teacher: "Dr. Sarah Wilson"
+ },
+ {
+ id: "11-sigma-1",
+ name: "Sigma",
+ standard: "11th Class",
+ subjects: ["Mathematics", "Chemistry", "Physics"],
+ totalStudents: 120,
+ maxStudents: 180,
+ teacher: "Dr. Sarah Wilson"
+ },
+ {
+ id: "11-omega-2",
+ name: "Omega2",
+ standard: "11th Class",
+ subjects: ["Physics"],
+ totalStudents: 120,
+ maxStudents: 180,
+ teacher: "Dr. Sarah Wilson"
+ }
+ ]
+ },
+ {
+ name: "12th standard",
+ batches: [
+ {
+ id: "12-omega-1",
+ name: "Omega",
+ standard: "11th Class",
+ subjects: ["Chemistry"],
+ totalStudents: 120,
+ maxStudents: 180,
+ teacher: "Dr. Sarah Wilson"
+ },
+ {
+ id: "12-sigma-1",
+ name: "Sigma",
+ standard: "11th Class",
+ subjects: ["Mathematics"],
+ totalStudents: 120,
+ maxStudents: 180,
+ teacher: "Dr. Sarah Wilson"
+ },
+ {
+ id: "12-omega-2",
+ name: "Omega2",
+ standard: "11th Class",
+ subjects: ["Physics"],
+ totalStudents: 120,
+ maxStudents: 180,
+ teacher: "Dr. Sarah Wilson"
+ }
+ ]
+ }
+ ]
+};
+
+export async function GET(request: NextRequest) {
+ try {
+ // Get query parameters for filtering
+ const searchParams = request.nextUrl.searchParams;
+ const standard = searchParams.get('standard');
+ const subject = searchParams.get('subject');
+ const teacher = searchParams.get('teacher');
+
+ // Filter the data based on query parameters
+ let filteredData = { ...batchesData };
+
+ if (standard) {
+ filteredData.standards = filteredData.standards.filter(
+ std => std.name.toLowerCase().includes(standard.toLowerCase())
+ );
+ }
+
+ // Filter batches within each standard
+ filteredData.standards = filteredData.standards.map(std => {
+ let filteredBatches = [...std.batches];
+
+ if (subject) {
+ filteredBatches = filteredBatches.filter(batch =>
+ batch.subjects.some(s => s.toLowerCase().includes(subject.toLowerCase()))
+ );
+ }
+
+ if (teacher) {
+ filteredBatches = filteredBatches.filter(batch =>
+ batch.teacher.toLowerCase().includes(teacher.toLowerCase())
+ );
+ }
+
+ return {
+ ...std,
+ batches: filteredBatches
+ };
+ });
+
+ // Remove standards with no batches after filtering
+ filteredData.standards = filteredData.standards.filter(std => std.batches.length > 0);
+
+ return NextResponse.json(filteredData, { status: 200 });
+ } catch (error) {
+ console.error('Error fetching batches:', error);
+ return NextResponse.json(
+ { error: 'Failed to fetch batches' },
+ { status: 500 }
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/app/globals.css b/src/app/globals.css
index 9817d51..ae5f5d0 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -5,66 +5,81 @@
@layer base {
:root {
--background: 0 0% 100%;
- --foreground: 222.2 84% 4.9%;
+ --foreground: 0 0% 3.9%;
--card: 0 0% 100%;
- --card-foreground: 222.2 84% 4.9%;
+ --card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
- --popover-foreground: 222.2 84% 4.9%;
+ --popover-foreground: 0 0% 3.9%;
- --primary: 265 88% 64%;
- --primary-foreground: 210 40% 98%;
+ --primary: 0 0% 9%;
+ --primary-foreground: 0 0% 98%;
- --secondary: 210 40% 96.1%;
- --secondary-foreground: 222.2 47.4% 11.2%;
+ --secondary: 0 0% 96.1%;
+ --secondary-foreground: 0 0% 9%;
--sidebar-background: 262, 86%, 46%, 0.03;
- --muted: 210 40% 96.1%;
- --muted-foreground: 215.4 16.3% 46.9%;
+ --muted: 0 0% 96.1%;
+ --muted-foreground: 0 0% 45.1%;
- --accent: 210 40% 96.1%;
- --accent-foreground: 222.2 47.4% 11.2%;
+ --accent: 0 0% 96.1%;
+ --accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
- --destructive-foreground: 210 40% 98%;
+ --destructive-foreground: 0 0% 98%;
- --border: 214.3 31.8% 91.4%;
- --input: 214.3 31.8% 91.4%;
- --ring: 222.2 84% 4.9%;
+ --border: 0 0% 89.8%;
+ --input: 0 0% 89.8%;
+ --ring: 0 0% 3.9%;
--radius: 0.5rem;
+
+ --chart-1: 12 76% 61%;
+
+ --chart-2: 173 58% 39%;
+
+ --chart-3: 197 37% 24%;
+
+ --chart-4: 43 74% 66%;
+
+ --chart-5: 27 87% 67%;
}
.dark {
- --background: 222.2 84% 4.9%;
- --foreground: 210 40% 98%;
+ --background: 0 0% 3.9%;
+ --foreground: 0 0% 98%;
- --card: 222.2 84% 4.9%;
- --card-foreground: 210 40% 98%;
+ --card: 0 0% 3.9%;
+ --card-foreground: 0 0% 98%;
- --popover: 222.2 84% 4.9%;
- --popover-foreground: 210 40% 98%;
+ --popover: 0 0% 3.9%;
+ --popover-foreground: 0 0% 98%;
- --primary: 210 40% 98%;
- --primary-foreground: 222.2 47.4% 11.2%;
+ --primary: 0 0% 98%;
+ --primary-foreground: 0 0% 9%;
- --secondary: 217.2 32.6% 17.5%;
- --secondary-foreground: 210 40% 98%;
+ --secondary: 0 0% 14.9%;
+ --secondary-foreground: 0 0% 98%;
- --muted: 217.2 32.6% 17.5%;
- --muted-foreground: 215 20.2% 65.1%;
+ --muted: 0 0% 14.9%;
+ --muted-foreground: 0 0% 63.9%;
- --accent: 217.2 32.6% 17.5%;
- --accent-foreground: 210 40% 98%;
+ --accent: 0 0% 14.9%;
+ --accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
- --destructive-foreground: 210 40% 98%;
-
- --border: 217.2 32.6% 17.5%;
- --input: 217.2 32.6% 17.5%;
- --ring: 212.7 26.8% 83.9%;
+ --destructive-foreground: 0 0% 98%;
+
+ --border: 0 0% 14.9%;
+ --input: 0 0% 14.9%;
+ --ring: 0 0% 83.1%;
+ --chart-1: 220 70% 50%;
+ --chart-2: 160 60% 45%;
+ --chart-3: 30 80% 55%;
+ --chart-4: 280 65% 60%;
+ --chart-5: 340 75% 55%;
}
}
@@ -109,3 +124,15 @@
scrollbar-width: none; /* Firefox */
}
}
+
+.flex-center{
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.flex-between{
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
\ No newline at end of file
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index d178a3f..63a5ec6 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,11 +1,13 @@
import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";
+import { Mada } from "next/font/google";
export const metadata: Metadata = {
title: "Leadlly | Admin",
description: "Admin dashboard by leadlly",
};
+const mada = Mada({ subsets: ["latin"], weight: ["400", "700"] }); // Load Mada font
export default function RootLayout({
children,
@@ -14,8 +16,7 @@ export default function RootLayout({
}>) {
return (
-
+
{children}
diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx
new file mode 100644
index 0000000..65d4fcd
--- /dev/null
+++ b/src/components/ui/button.tsx
@@ -0,0 +1,57 @@
+import * as React from "react"
+import { Slot } from "@radix-ui/react-slot"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
+ {
+ variants: {
+ variant: {
+ default:
+ "bg-primary text-primary-foreground shadow hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
+ outline:
+ "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-9 px-4 py-2",
+ sm: "h-8 rounded-md px-3 text-xs",
+ lg: "h-10 rounded-md px-8",
+ icon: "h-9 w-9",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean
+}
+
+const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button"
+ return (
+
+ )
+ }
+)
+Button.displayName = "Button"
+
+export { Button, buttonVariants }
diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx
new file mode 100644
index 0000000..cabfbfc
--- /dev/null
+++ b/src/components/ui/card.tsx
@@ -0,0 +1,76 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Card = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+Card.displayName = "Card"
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardHeader.displayName = "CardHeader"
+
+const CardTitle = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardTitle.displayName = "CardTitle"
+
+const CardDescription = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardDescription.displayName = "CardDescription"
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardContent.displayName = "CardContent"
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardFooter.displayName = "CardFooter"
+
+export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx
new file mode 100644
index 0000000..69b64fb
--- /dev/null
+++ b/src/components/ui/input.tsx
@@ -0,0 +1,22 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Input = React.forwardRef>(
+ ({ className, type, ...props }, ref) => {
+ return (
+
+ )
+ }
+)
+Input.displayName = "Input"
+
+export { Input }
diff --git a/src/components/ui/progress.tsx b/src/components/ui/progress.tsx
new file mode 100644
index 0000000..eb92507
--- /dev/null
+++ b/src/components/ui/progress.tsx
@@ -0,0 +1,29 @@
+"use client"
+
+import * as React from "react"
+import * as ProgressPrimitive from "@radix-ui/react-progress"
+
+import { cn } from "@/lib/utils"
+
+const Progress = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & { indicatorColor?: string }
+>(({ className, value, indicatorColor = "bg-primary", ...props }, ref) => (
+
+
+
+))
+
+Progress.displayName = ProgressPrimitive.Root.displayName
+
+export { Progress }
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
new file mode 100644
index 0000000..bd0c391
--- /dev/null
+++ b/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx"
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs))
+}
diff --git a/src/types/batches.ts b/src/types/batches.ts
new file mode 100644
index 0000000..20e670e
--- /dev/null
+++ b/src/types/batches.ts
@@ -0,0 +1,24 @@
+export interface Batch {
+ id: string;
+ name: string;
+ standard: string;
+ subjects: string[];
+ totalStudents: number;
+ maxStudents: number;
+ teacher: string;
+}
+
+export interface Standard {
+ name: string;
+ batches: Batch[];
+}
+
+export interface BatchesData {
+ standards: Standard[];
+}
+
+export type BatchFilters = {
+ standard: string;
+ subject: string;
+ teacher: string;
+};
diff --git a/src/types/students.ts b/src/types/students.ts
new file mode 100644
index 0000000..b2db81e
--- /dev/null
+++ b/src/types/students.ts
@@ -0,0 +1,8 @@
+export interface Student {
+ name: string;
+ class: number;
+ level: number;
+ status: "excellent" | "optimal" | "inefficient";
+}
+
+export const options = ["all", "excellent", "optimal", "inefficient"];
\ No newline at end of file
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 2873606..3cb74f6 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -11,111 +11,143 @@ const config = {
],
prefix: '',
theme: {
- container: {
- center: true,
- padding: '2rem',
- screens: {
- '2xl': '1400px',
- },
- },
- extend: {
- screens: {
- '2xl': '1400px',
- },
- fontFamily: {
- sans: ['var(--font-sans)', ...fontFamily.sans],
- },
- colors: {
- border: 'hsl(var(--border))',
- input: 'hsl(var(--input))',
- ring: 'hsl(var(--ring))',
- background: 'hsl(var(--background))',
- foreground: 'hsl(var(--foreground))',
- 'sidebar-background': 'hsla(262, 86%, 46%, 0.03)',
- primary: {
- DEFAULT: 'hsl(var(--primary))',
- foreground: 'hsl(var(--primary-foreground))',
- },
- secondary: {
- DEFAULT: 'hsl(var(--secondary))',
- foreground: 'hsl(var(--secondary-foreground))',
- },
- destructive: {
- DEFAULT: 'hsl(var(--destructive))',
- foreground: 'hsl(var(--destructive-foreground))',
- },
- muted: {
- DEFAULT: 'hsl(var(--muted))',
- foreground: 'hsl(var(--muted-foreground))',
- },
- accent: {
- DEFAULT: 'hsl(var(--accent))',
- foreground: 'hsl(var(--accent-foreground))',
- },
- popover: {
- DEFAULT: 'hsl(var(--popover))',
- foreground: 'hsl(var(--popover-foreground))',
- },
- card: {
- DEFAULT: 'hsl(var(--card))',
- foreground: 'hsl(var(--card-foreground))',
- },
- },
- borderRadius: {
- lg: 'var(--radius)',
- md: 'calc(var(--radius) - 2px)',
- sm: 'calc(var(--radius) - 4px)',
- },
- keyframes: {
- 'accordion-down': {
- from: { height: '0' },
- to: { height: 'var(--radix-accordion-content-height)' },
- },
- 'accordion-up': {
- from: { height: 'var(--radix-accordion-content-height)' },
- to: { height: '0' },
- },
- 'collapsible-down': {
- from: { height: '0' },
- to: { height: 'var(--radix-collapsible-content-height)' },
- },
- 'collapsible-up': {
- from: { height: 'var(--radix-collapsible-content-height)' },
- to: { height: '0' },
- },
- 'caret-blink': {
- '0%,70%,100%': { opacity: '1' },
- '20%,50%': { opacity: '0' },
- },
- },
- animation: {
- 'accordion-down': 'accordion-down 0.2s ease-out',
- 'accordion-up': 'accordion-up 0.2s ease-out',
- 'collapsible-down': 'collapsible-down 0.2s ease-out',
- 'collapsible-up': 'collapsible-up 0.2s ease-out',
- 'caret-blink': 'caret-blink 1.25s ease-out infinite',
- },
- fontSize: {
- 'page-title': ['40px', '52px'],
- },
- width: {
- sidebar: '261px',
- },
- height: {
- 'main-height': 'calc(100dvh - 24px)',
- },
- boxShadow: {
- custom: '0px 17px 37px 0px rgba(165, 92, 255, 0.0)',
- dialog: '0 0 21.5px 2px rgba(0, 0, 0, 0.29)',
- tracker_subject_overview:
- '2px 1px 10.5px 0 rgba(151, 83, 245, 0.18), inset 0 0 32px -7px rgba(151, 83, 245, 0.18)',
- question: ' 0px 0px 26.7px -10px #00000033',
- 'custom-back': 'inset 1.68px 3.37px 5.31px 0 rgba(0, 0, 0, 0.1)',
- 'section':' 0px 1px 24.8px -9px #00000038',
- 'card':'0px 1.15px 21.31px 0px #FF990012'
- },
- },
- },
+ container: {
+ center: true,
+ padding: '2rem',
+ screens: {
+ '2xl': '1400px'
+ }
+ },
+ extend: {
+ screens: {
+ '2xl': '1400px'
+ },
+ fontFamily: {
+ sans: [
+ 'var(--font-sans)',
+ ...fontFamily.sans
+ ]
+ },
+ colors: {
+ border: 'hsl(var(--border))',
+ input: 'hsl(var(--input))',
+ ring: 'hsl(var(--ring))',
+ background: 'hsl(var(--background))',
+ foreground: 'hsl(var(--foreground))',
+ 'sidebar-background': 'hsla(262, 86%, 46%, 0.03)',
+ primary: {
+ DEFAULT: 'hsl(var(--primary))',
+ foreground: 'hsl(var(--primary-foreground))'
+ },
+ secondary: {
+ DEFAULT: 'hsl(var(--secondary))',
+ foreground: 'hsl(var(--secondary-foreground))'
+ },
+ destructive: {
+ DEFAULT: 'hsl(var(--destructive))',
+ foreground: 'hsl(var(--destructive-foreground))'
+ },
+ muted: {
+ DEFAULT: 'hsl(var(--muted))',
+ foreground: 'hsl(var(--muted-foreground))'
+ },
+ accent: {
+ DEFAULT: 'hsl(var(--accent))',
+ foreground: 'hsl(var(--accent-foreground))'
+ },
+ popover: {
+ DEFAULT: 'hsl(var(--popover))',
+ foreground: 'hsl(var(--popover-foreground))'
+ },
+ card: {
+ DEFAULT: 'hsl(var(--card))',
+ foreground: 'hsl(var(--card-foreground))'
+ },
+ chart: {
+ '1': 'hsl(var(--chart-1))',
+ '2': 'hsl(var(--chart-2))',
+ '3': 'hsl(var(--chart-3))',
+ '4': 'hsl(var(--chart-4))',
+ '5': 'hsl(var(--chart-5))'
+ }
+ },
+ borderRadius: {
+ lg: 'var(--radius)',
+ md: 'calc(var(--radius) - 2px)',
+ sm: 'calc(var(--radius) - 4px)'
+ },
+ keyframes: {
+ 'accordion-down': {
+ from: {
+ height: '0'
+ },
+ to: {
+ height: 'var(--radix-accordion-content-height)'
+ }
+ },
+ 'accordion-up': {
+ from: {
+ height: 'var(--radix-accordion-content-height)'
+ },
+ to: {
+ height: '0'
+ }
+ },
+ 'collapsible-down': {
+ from: {
+ height: '0'
+ },
+ to: {
+ height: 'var(--radix-collapsible-content-height)'
+ }
+ },
+ 'collapsible-up': {
+ from: {
+ height: 'var(--radix-collapsible-content-height)'
+ },
+ to: {
+ height: '0'
+ }
+ },
+ 'caret-blink': {
+ '0%,70%,100%': {
+ opacity: '1'
+ },
+ '20%,50%': {
+ opacity: '0'
+ }
+ }
+ },
+ animation: {
+ 'accordion-down': 'accordion-down 0.2s ease-out',
+ 'accordion-up': 'accordion-up 0.2s ease-out',
+ 'collapsible-down': 'collapsible-down 0.2s ease-out',
+ 'collapsible-up': 'collapsible-up 0.2s ease-out',
+ 'caret-blink': 'caret-blink 1.25s ease-out infinite'
+ },
+ fontSize: {
+ 'page-title': [
+ '40px',
+ '52px'
+ ]
+ },
+ width: {
+ sidebar: '261px'
+ },
+ height: {
+ 'main-height': 'calc(100dvh - 24px)'
+ },
+ boxShadow: {
+ custom: '0px 17px 37px 0px rgba(165, 92, 255, 0.0)',
+ dialog: '0 0 21.5px 2px rgba(0, 0, 0, 0.29)',
+ tracker_subject_overview: '2px 1px 10.5px 0 rgba(151, 83, 245, 0.18), inset 0 0 32px -7px rgba(151, 83, 245, 0.18)',
+ question: ' 0px 0px 26.7px -10px #00000033',
+ 'custom-back': 'inset 1.68px 3.37px 5.31px 0 rgba(0, 0, 0, 0.1)',
+ section: ' 0px 1px 24.8px -9px #00000038',
+ card: '0px 1.15px 21.31px 0px #FF990012'
+ }
+ }
+ },
plugins: [require('tailwindcss-animate')],
} satisfies Config;