Refactor internify components and services

- Updated LoginInternify to remove unnecessary state initialization.
- Cleaned up NotificationList by removing unused code and fixing button click handler.
- Added project_id prop to InternClaimCert for better data handling.
- Enhanced CertificateNotAvailable to include claim functionality with loading and error states.
- Modified HomeHeader to display a default user name.
- Corrected ProjectTimeline to import ProjectTask from the correct type file.
- Implemented loading and error handling in CertificateListPage.
- Improved MentorProjectDetailPage to handle task updates and navigation correctly.
- Enhanced MentorSettingsPage to manage profile picture errors and state.
- Updated AddInternsDialog to use the correct hook for fetching interns.
- Refactored EditSubmissionTask to handle task updates and errors more effectively.
- Improved MentorProjectCard to include project archiving functionality.
- Removed deprecated useInterns hook and replaced it with useUser for fetching user data.
- Added new useMentors hook for managing mentor-related operations.
- Cleaned up CertificateService by removing unused verifyCertificate function.
- Created MentorServices for managing mentor data operations.
- Updated UserService to include fetching Mahasiswa data and removed unused UserServices file.
This commit is contained in:
Kemas M. Aryadary Rasyad
2026-06-29 15:42:48 +07:00
parent 4084ccf1bf
commit da67ad86d8
29 changed files with 1099 additions and 5581 deletions
@@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom'
import * as LucideIcons from 'lucide-react';
import type { LucideProps } from 'lucide-react';
import type { Project } from '../../../../types/project.types';
import { useArchiveProject } from '../../../../hooks/useProjects';
const getDynamicIcon = (iconName: string) => {
const formatted = iconName.charAt(0).toUpperCase() + iconName.slice(1);
@@ -14,14 +15,28 @@ const toSlug = (name: string) => name.toLowerCase().replace(/\s+/g, '-');
export default function MentorProjectCard(project: Project) {
const navigate = useNavigate();
const { archive, loading } = useArchiveProject();
const handleCardClick = () => {
navigate(`/mentor/projects/${toSlug(project.slug)}`)
};
const Icon = getDynamicIcon(project.project_icon);
const handleDeleteClick = (e: React.MouseEvent<HTMLButtonElement>) => {
const handleDeleteClick = async (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
}
const confirmed = window.confirm(`Arsipkan project "${project.project_name}"?`);
if (!confirmed) return;
const result = await archive(project.id);
if (result) {
window.alert("Project berhasil diarsipkan.");
window.location.reload();
} else {
window.alert("Gagal mengarsipkan project.");
}
};
return (
<div
onClick={handleCardClick}
@@ -50,7 +65,12 @@ export default function MentorProjectCard(project: Project) {
{/* Footer */}
<div className="border-t border-gray-300 text-gray-400 flex justify-end p-2 bg-gray-50/50">
<button onClick={handleDeleteClick} className="hover:text-red-600 transition-colors">
<button
onClick={handleDeleteClick}
disabled={loading}
className="hover:text-red-600 transition-colors disabled:opacity-50"
aria-label={`Archive ${project.project_name}`}
>
<Trash2 className="w-4 h-4" />
</button>
</div>