OneCompiler

Front end part

123

import React, { useState, useEffect } from 'react';
import { AlertCircle, BookOpen, UserPlus, User, LogIn } from 'lucide-react';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';

const CourseManagementSystem = () => {
const [courses, setCourses] = useState([]);
const [enrollments, setEnrollments] = useState([]);
const [user, setUser] = useState(null);
const [error, setError] = useState(null);
const [activeTab, setActiveTab] = useState('courses');

const baseUrl = 'http://localhost:8081/api';

const login = async (username, password) => {
try {
const response = await fetch(${baseUrl}/auth/login, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: username=${username}&password=${password},
credentials: 'include'
});
if (response.ok) {
const data = await response.json();
setUser({ username, role: data.role });
setError(null);
} else {
setError('Login failed');
}
} catch (err) {
setError(err.message);
}
};

const fetchCourses = async () => {
try {
const response = await fetch(${baseUrl}/courses/published, {
credentials: 'include'
});
if (response.ok) {
const data = await response.json();
setCourses(data);
}
} catch (err) {
setError(err.message);
}
};

const fetchEnrollments = async (userId) => {
try {
const response = await fetch(${baseUrl}/enrollments/student/${userId}, {
credentials: 'include'
});
if (response.ok) {
const data = await response.json();
setEnrollments(data);
}
} catch (err) {
setError(err.message);
}
};

const enroll = async (courseId) => {
try {
const response = await fetch(${baseUrl}/enrollments, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
studentId: user.id,
courseId: courseId
}),
credentials: 'include'
});
if (response.ok) {
fetchEnrollments(user.id);
}
} catch (err) {
setError(err.message);
}
};

// Login Form Component
const LoginForm = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');

return (
  <div className="max-w-md mx-auto mt-8 p-6 bg-white rounded-lg shadow-md">
    <div className="flex items-center gap-2 mb-6">
      <LogIn className="w-6 h-6" />
      <h2 className="text-2xl font-bold">Login</h2>
    </div>
    <form onSubmit={(e) => {
      e.preventDefault();
      login(username, password);
    }}>
      <div className="mb-4">
        <label className="block text-sm font-medium mb-2">Username</label>
        <input
          type="text"
          value={username}
          onChange={(e) => setUsername(e.target.value)}
          className="w-full p-2 border rounded"
        />
      </div>
      <div className="mb-6">
        <label className="block text-sm font-medium mb-2">Password</label>
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          className="w-full p-2 border rounded"
        />
      </div>
      <button
        type="submit"
        className="w-full bg-blue-600 text-white py-2 px-4 rounded hover:bg-blue-700"
      >
        Login
      </button>
    </form>
  </div>
);

};

// Course List Component
const CourseList = () => (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 p-6">
{courses.map(course => (
<div key={course.id} className="bg-white p-6 rounded-lg shadow-md">
<div className="flex items-center gap-2 mb-4">
<BookOpen className="w-6 h-6 text-blue-600" />
<h3 className="text-xl font-bold">{course.title}</h3>
</div>
<p className="text-gray-600 mb-4">{course.description}</p>
<div className="flex justify-between items-center">
<span className="font-bold text-lg">${course.price}</span>
<button
onClick={() => enroll(course.id)}
className="bg-blue-600 text-white py-2 px-4 rounded hover:bg-blue-700"
>
Enroll
</button>
</div>
</div>
))}
</div>
);

// Enrollments List Component
const EnrollmentsList = () => (
<div className="p-6">
<div className="grid gap-6">
{enrollments.map(enrollment => (
<div key={enrollment.id} className="bg-white p-6 rounded-lg shadow-md">
<div className="flex justify-between items-center mb-4">
<h3 className="text-xl font-bold">{enrollment.course.title}</h3>
<span className="text-blue-600 font-bold">
{enrollment.progress}% Complete
</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-2.5">
<div
className="bg-blue-600 h-2.5 rounded-full"
style={{ width: ${enrollment.progress}% }}
></div>
</div>
</div>
))}
</div>
</div>
);

return (
<div className="min-h-screen bg-gray-100">
{error && (
<Alert variant="destructive" className="m-4">
<AlertCircle className="h-4 w-4" />
<AlertTitle>Error</AlertTitle>
<AlertDescription>{error}</AlertDescription>
</Alert>
)}

  {!user ? (
    <LoginForm />
  ) : (
    <div>
      <nav className="bg-white shadow-md">
        <div className="max-w-7xl mx-auto px-4">
          <div className="flex justify-between h-16">
            <div className="flex">
              <button
                onClick={() => setActiveTab('courses')}
                className={`px-3 inline-flex items-center h-full border-b-2 ${
                  activeTab === 'courses'
                    ? 'border-blue-600 text-blue-600'
                    : 'border-transparent'
                }`}
              >
                <BookOpen className="w-5 h-5 mr-2" />
                Courses
              </button>
              <button
                onClick={() => setActiveTab('enrollments')}
                className={`px-3 inline-flex items-center h-full border-b-2 ${
                  activeTab === 'enrollments'
                    ? 'border-blue-600 text-blue-600'
                    : 'border-transparent'
                }`}
              >
                <UserPlus className="w-5 h-5 mr-2" />
                My Enrollments
              </button>
            </div>
            <div className="flex items-center">
              <User className="w-5 h-5 mr-2" />
              <span className="font-medium">{user.username}</span>
            </div>
          </div>
        </div>
      </nav>

      <main className="max-w-7xl mx-auto py-6">
        {activeTab === 'courses' ? <CourseList /> : <EnrollmentsList />}
      </main>
    </div>
  )}
</div>

);
};

export default CourseManagementSystem;