Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 31 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# 🎓 LMS Frontend
# 🎓 Shiners LMS Client

Ini adalah **Frontend Project** untuk aplikasi Learning Management System (LMS).
Dibangun menggunakan **React + Vite** dengan fokus pada tampilan **modern, responsive, dan mudah digunakan**.
**Shiners LMS** is the frontend project of a **Learning Management System** (LMS). Built with **React + Vite**, this project prioritizes a **modern, responsive, and intuitive** user experience for students, instructors, and administrators alike.

---
***

## 🚀 Tech Stack

Expand All @@ -13,70 +12,69 @@ Dibangun menggunakan **React + Vite** dengan fokus pada tampilan **modern, respo
![TanStack Query](https://img.shields.io/badge/TanStack_Query-FF4154?style=for-the-badge&logo=reactquery&logoColor=white)
![React Router](https://img.shields.io/badge/React_Router-CA4245?style=for-the-badge&logo=reactrouter&logoColor=white)

---

## 📂 Struktur Folder

```
frontend-lms/
│── public/ # aset statis (gambar, ikon, dsb)
lms-client/
│── public/ # Static assets (images, icons, etc.)
│── src/
│ │── assets/ # gambar, icon
│ │── components/ # komponen UI reusable
│ │── pages/ # halaman utama (Dashboard, Login, dll)
│ │── routes/ # konfigurasi routing
│ │── hooks/ # custom hooks
│ │── services/ # API call (axios/fetch)
| │── store/ # store zustand
│ │── App.jsx # root component
│ │── main.jsx # entry point React
│── package.json
│── vite.config.js
│── tailwind.config.js
```

---
***

## ⚙️ Cara Install & Menjalankan
## ⚙️ Installation & Setup

1. **Clone repo**
1. **Clone the repository**
```bash
git clone https://github.com/username/lms-frontend.git
cd lms-frontend
git clone https://github.com/HSI-Boarding-School/lms-client.git
cd lms-client
```

2. **Install dependencies**
```bash
bun install
```

3. **Jalankan project**
3. **Run the development server**
```bash
bun run dev
bun dev
```

4. Buka di browser: [http://localhost:5173](http://localhost:5173)
4. **Open your browser**
[http://localhost:5173](http://localhost:5173)

***

---
## 🌟 Key Features

## 🌟 Fitur Utama (Frontend)
- ✅ Multi-role dashboards for **Students**, **Instructors**, and **Admins**
- ✅ Course Management (list, details, enrollment)
- ✅ Quizzes & Assignments user interface
- ✅ Modern responsive design for desktop and mobile devices
- ✅ Integration-ready with HSI’s internal API services

- ✅ Dashboard Student, Instructor, Admin
- ✅ Manajemen Courses (list, detail, enroll)
- ✅ Manajemen Quizzes & Assignments (UI saja dulu)
- ✅ Responsive Design (desktop & mobile)
***

---
## 🏫 About the Project

## 📌 Catatan
Shiners LMS is designed to support digital learning and management activities within the **HSI Boarding School network** across Indonesia.

- Ini hanya bagian **Frontend**.
- Untuk API/Backend gunakan repo terpisah (misalnya dengan Node.js/Express/FastAPI).
- Pastikan setting `.env` sesuai dengan URL backend.
It provides a centralized platform for educational materials, quizzes, and course progress tracking for both teachers and students.

---
***

## 👨‍💻 Author
## 📌 Notes

- Nama: **Muhammad Hamka**
- Role: Frontend Developer
- This repository contains the **frontend only**.
- The **backend/API service** should be implemented in a separate project (Go-lang).
- Ensure the `.env` file is configured with the correct backend base URL.
97 changes: 95 additions & 2 deletions bun.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion components.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
Expand Down
17 changes: 10 additions & 7 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="/public/logo.webp" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>EduFlow - Next-Generation LMS</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<title>HSI BS LMS</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap"
rel="stylesheet"
/>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
</html>
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,21 @@
"preview": "vite preview"
},
"dependencies": {
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-slot": "^1.2.3",
"@supabase/supabase-js": "^2.57.4",
"@tanstack/react-query": "^5.90.2",
"@tanstack/react-query-devtools": "^5.90.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.544.0",
"lucide-react": "^0.546.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router": "^7.9.4",
"tailwind-merge": "^3.3.1",
"tailwindcss-animate": "^1.0.7"
"tailwindcss-animate": "^1.0.7",
"zustand": "^5.0.8"
},
"devDependencies": {
"@eslint/js": "^9.9.1",
Expand Down
Binary file added public/logo.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
139 changes: 14 additions & 125 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,131 +1,20 @@
import { useState, useEffect } from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { ThemeProvider } from "./context/ThemeContext";
import { Header } from "./components/Header";
import { Sidebar } from "./components/Sidebar";
import { StudentDashboard } from "./components/dashboards/StudentDashboard";
import { InstructorDashboard } from "./components/dashboards/InstructorDashboard";
import { AdminDashboard } from "./components/dashboards/AdminDashboard";
import { useUser } from "./hooks/useData";
import { Menu } from "lucide-react";

const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
retry: 1,
},
},
});

function AppContent() {
const [currentView, setCurrentView] = useState("dashboard");
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
const [userRole, setUserRole] = useState<"student" | "instructor" | "admin">(
"student"
);
const { data: user } = useUser();

useEffect(() => {
if (user) {
setUserRole(user.role);
}
}, [user]);

const renderDashboard = () => {
switch (userRole) {
case "instructor":
return <InstructorDashboard />;
case "admin":
return <AdminDashboard />;
default:
return <StudentDashboard />;
}
};

return (
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 transition-colors duration-300">
<Sidebar
userRole={userRole}
currentView={currentView}
onViewChange={setCurrentView}
isCollapsed={sidebarCollapsed}
onToggle={() => setSidebarCollapsed(!sidebarCollapsed)}
/>

<div
className={`transition-all duration-300 ${
sidebarCollapsed ? "lg:ml-20" : "lg:ml-64"
}`}
>
{/* Mobile menu button */}
<button
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
className="lg:hidden fixed top-4 left-4 z-50 p-2 bg-white dark:bg-gray-800 rounded-lg shadow-lg"
>
<Menu className="h-6 w-6" />
</button>

<Header />

<main className="p-6 lg:p-8">
<div className="max-w-7xl mx-auto">{renderDashboard()}</div>
</main>
</div>

{/* Demo Controls */}
<div className="fixed bottom-6 right-6 z-40">
<div className="bg-white/90 dark:bg-gray-900/90 backdrop-blur-xl rounded-2xl p-4 shadow-xl border border-gray-200 dark:border-gray-700">
<p className="text-sm font-medium text-gray-900 dark:text-white mb-3">
Demo Mode
</p>
<div className="space-y-2">
<button
onClick={() => setUserRole("student")}
className={`w-full text-left px-3 py-2 rounded-lg text-sm transition-colors ${
userRole === "student"
? "bg-blue-100 dark:bg-blue-900 text-blue-900 dark:text-blue-100"
: "text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800"
}`}
>
Student View
</button>
<button
onClick={() => setUserRole("instructor")}
className={`w-full text-left px-3 py-2 rounded-lg text-sm transition-colors ${
userRole === "instructor"
? "bg-blue-100 dark:bg-blue-900 text-blue-900 dark:text-blue-100"
: "text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800"
}`}
>
Instructor View
</button>
<button
onClick={() => setUserRole("admin")}
className={`w-full text-left px-3 py-2 rounded-lg text-sm transition-colors ${
userRole === "admin"
? "bg-blue-100 dark:bg-blue-900 text-blue-900 dark:text-blue-100"
: "text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800"
}`}
>
Admin View
</button>
</div>
</div>
</div>
</div>
);
}
import { Route, Routes } from "react-router";
import AppContent from "./pages/dashboards/AppContent";
import LoginPage from "./pages/auth/LoginPage";
import SignUpPage from "./pages/auth/SignUpPage";
import ForgotPasswordPage from "./pages/auth/ForgotPasswordPage";
import ResetPasswordPage from "./pages/auth/ResetPasswordPage";

function App() {
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider>
<AppContent />
<ReactQueryDevtools initialIsOpen={false} />
</ThemeProvider>
</QueryClientProvider>
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route path="/signup" element={<SignUpPage />} />
<Route path="/forgot-password" element={<ForgotPasswordPage />} />
<Route path="/reset-password" element={<ResetPasswordPage />} />

<Route path="/*" element={<AppContent />} />
</Routes>
);
}

Expand Down
Loading