import React, { useState, useEffect } from "react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { PlusCircle, Search, Loader2, Edit, Trash2, Save, X, Plus } from "lucide-react"; import { Label } from "@/components/ui/label"; import CustomDialog from "@/components/CustomDialog"; import { featureApi } from "@/services/featureApi"; import { Feature, FeatureCreateRequest, FeatureUpdateRequest } from "@/types"; import Header from "@/components/layout/header"; import Sidebar from "@/components/layout/sidebar"; import { useIsMobile } from "@/hooks/use-mobile"; import { toast } from "@/lib/custom-toast"; import { Checkbox } from "@/components/ui/checkbox"; import { Badge } from "@/components/ui/badge"; const Features = () => { const queryClient = useQueryClient(); const isMobile = useIsMobile(); const [isSidebarOpen, setIsSidebarOpen] = useState(!isMobile); const [searchQuery, setSearchQuery] = useState(""); const [isAddDialogOpen, setIsAddDialogOpen] = useState(false); const [newFeatureName, setNewFeatureName] = useState(""); const [newFeatureDescription, setNewFeatureDescription] = useState(""); const [newFeatureCategory, setNewFeatureCategory] = useState(""); const [newFeatureStatus, setNewFeatureStatus] = useState(true); const [editingFeature, setEditingFeature] = useState(null); const [editFeatureName, setEditFeatureName] = useState(""); const [editFeatureDescription, setEditFeatureDescription] = useState(""); const [editFeatureCategory, setEditFeatureCategory] = useState(""); const [editFeatureStatus, setEditFeatureStatus] = useState(true); // Fetch features const { data: features = [], isLoading, error, refetch } = useQuery({ queryKey: ["features"], queryFn: featureApi.getAll, }); // Create feature mutation const createMutation = useMutation({ mutationFn: featureApi.create, onSuccess: () => { toast.success("Feature created successfully"); queryClient.invalidateQueries({ queryKey: ["features"] }); setIsAddDialogOpen(false); setNewFeatureName(""); }, onError: (error) => { toast.error("Failed to create feature"); console.error("Error creating feature:", error); } }); // Update feature mutation const updateMutation = useMutation({ mutationFn: ({ id, feature }: { id: number, feature: FeatureUpdateRequest }) => featureApi.update(id, feature), onSuccess: () => { toast.success("Feature updated successfully"); queryClient.invalidateQueries({ queryKey: ["features"] }); setEditingFeature(null); }, onError: (error) => { toast.error("Failed to update feature"); console.error("Error updating feature:", error); } }); // Delete feature mutation const deleteMutation = useMutation({ mutationFn: featureApi.delete, onSuccess: () => { toast.success("Feature deleted successfully"); queryClient.invalidateQueries({ queryKey: ["features"] }); }, onError: (error) => { toast.error("Failed to delete feature"); console.error("Error deleting feature:", error); } }); // Toggle sidebar const toggleSidebar = () => { setIsSidebarOpen(!isSidebarOpen); }; // Handle create feature const handleCreateFeature = (e: React.FormEvent) => { e.preventDefault(); e.stopPropagation(); if (!newFeatureName.trim()) { toast.error("Feature name cannot be empty"); return; } const newFeature: FeatureCreateRequest = { featureId: 0, // This will be assigned by the server featureName: newFeatureName.trim(), description: newFeatureDescription.trim(), category: newFeatureCategory.trim(), isActive: newFeatureStatus }; createMutation.mutate(newFeature); }; // Handle create feature input change const handleCreateChange = (e: React.ChangeEvent) => { const { name, value } = e.target; switch(name) { case 'featureName': setNewFeatureName(value); break; case 'featureDescription': setNewFeatureDescription(value); break; case 'featureCategory': setNewFeatureCategory(value); break; default: break; } }; // Handle edit feature const handleEditFeature = (feature: Feature) => { setEditingFeature(feature); setEditFeatureName(feature.featureName); setEditFeatureDescription(feature.description || ""); setEditFeatureCategory(feature.category || ""); setEditFeatureStatus(feature.isActive !== undefined ? feature.isActive : true); }; // Handle update feature const handleUpdateFeature = () => { if (!editingFeature) return; if (!editFeatureName.trim()) { toast.error("Feature name cannot be empty"); return; } const updatedFeature: FeatureUpdateRequest = { featureId: editingFeature.featureId, featureName: editFeatureName.trim(), description: editFeatureDescription.trim(), category: editFeatureCategory.trim(), isActive: editFeatureStatus }; updateMutation.mutate({ id: editingFeature.featureId, feature: updatedFeature }); }; // Handle delete feature const handleDeleteFeature = (id: number) => { if (window.confirm("Are you sure you want to delete this feature?")) { deleteMutation.mutate(id); } }; // Cancel editing const cancelEditing = () => { setEditingFeature(null); }; // Filter features based on search query const filteredFeatures = features?.filter((feature: Feature) => { if (!searchQuery) return true; const query = searchQuery.toLowerCase(); return feature.featureName.toLowerCase().includes(query); }); // Function to ensure all standard features exist in the database const ensureAllMissingFeatures = async () => { try { const existingFeatures = await featureApi.getAll(); // Define all required features with unique IDs (1-53) const requiredFeatures = [ // Core features { featureId: 1, featureName: "Dashboard", description: "Main dashboard with overview statistics", category: "Core", isActive: true }, { featureId: 2, featureName: "Projects", description: "Project management and tracking", category: "Core", isActive: true }, { featureId: 3, featureName: "Deliverables", description: "Project deliverables management", category: "Project", isActive: true }, { featureId: 4, featureName: "Teams", description: "Team management and organization", category: "Core", isActive: true }, { featureId: 5, featureName: "Employees", description: "Employee management and profiles", category: "HR", isActive: true }, // Admin features { featureId: 6, featureName: "Roles", description: "Role management and permissions", category: "Administration", isActive: true }, { featureId: 7, featureName: "Permissions", description: "Permissions management", category: "Administration", isActive: true }, { featureId: 8, featureName: "Role Features", description: "Manage feature access for roles", category: "Administration", isActive: true }, // Project features { featureId: 9, featureName: "Backlog", description: "Product backlog management", category: "Project", isActive: true }, { featureId: 10, featureName: "Issues", description: "Issue tracking and resolution", category: "Project", isActive: true }, { featureId: 11, featureName: "Tasks", description: "Task tracking and assignment", category: "Project", isActive: true }, { featureId: 12, featureName: "Time Logs", description: "Time tracking for tasks and projects", category: "Project", isActive: true }, // Additional core features { featureId: 13, featureName: "Calendar", description: "Calendar view for events and deadlines", category: "Core", isActive: true }, { featureId: 14, featureName: "Reports", description: "Reporting and analytics", category: "Management", isActive: true }, { featureId: 15, featureName: "Messages", description: "Internal messaging system", category: "Communication", isActive: true }, { featureId: 16, featureName: "Settings", description: "System settings and configuration", category: "Administration", isActive: true }, { featureId: 17, featureName: "Notifications", description: "User notifications", category: "Core", isActive: true }, { featureId: 18, featureName: "Audit Logs", description: "Audit logs and security tracking", category: "Administration", isActive: true }, { featureId: 19, featureName: "Integrations", description: "Third-party system integrations", category: "Administration", isActive: true }, { featureId: 20, featureName: "File Management", description: "Document and file storage system", category: "Core", isActive: true }, // HR management features { featureId: 21, featureName: "Attendance", description: "Employee attendance tracking", category: "HR", isActive: true }, { featureId: 22, featureName: "Leaves", description: "Employee leave requests", category: "HR", isActive: true }, { featureId: 23, featureName: "Leaves Management", description: "Administrative leave management", category: "HR", isActive: true }, { featureId: 24, featureName: "Leave Types", description: "Configure leave types and policies", category: "HR", isActive: true }, { featureId: 42, featureName: "Leave Balances", description: "View your leave balances and history", category: "HR", isActive: true }, // Productivity features { featureId: 25, featureName: "Todos", description: "Personal to-do list management", category: "Productivity", isActive: true }, { featureId: 26, featureName: "Holidays", description: "Company holidays management", category: "HR", isActive: true }, { featureId: 27, featureName: "Bugs", description: "Bug tracking and resolution", category: "Project", isActive: true }, { featureId: 39, featureName: "Production Bugs", description: "Track and manage production bugs", category: "Project", isActive: true }, { featureId: 40, featureName: "Test Cases", description: "Create and manage test cases", category: "Project", isActive: true }, // Appraisal system features { featureId: 28, featureName: "My Appraisals", description: "Access to your own appraisals", category: "Appraisal", isActive: true }, { featureId: 29, featureName: "Appraisal Cycles", description: "Manage appraisal cycle periods", category: "Appraisal", isActive: true }, { featureId: 30, featureName: "Assessment Areas", description: "Manage assessment areas for appraisals", category: "Appraisal", isActive: true }, { featureId: 31, featureName: "Competencies", description: "Manage competencies for appraisals", category: "Appraisal", isActive: true }, { featureId: 32, featureName: "Manager Appraisals", description: "Access to team member appraisals for managers", category: "Appraisal", isActive: true }, { featureId: 36, featureName: "Role Assessment Questions", description: "Configure assessment questions per role", category: "Appraisal", isActive: true }, { featureId: 37, featureName: "HR Remarks", description: "HR comments on appraisals", category: "Appraisal", isActive: true }, { featureId: 38, featureName: "Management Remarks", description: "Management comments on appraisals", category: "Appraisal", isActive: true }, // Facilities features { featureId: 33, featureName: "Meeting Rooms", description: "Meeting room management", category: "Facilities", isActive: true }, { featureId: 34, featureName: "Room Bookings", description: "Book and schedule meeting rooms", category: "Facilities", isActive: true }, // Communication features { featureId: 35, featureName: "Communications", description: "Communication tools and channels", category: "Communication", isActive: true }, // Other Project & Management features { featureId: 41, featureName: "My Profile", description: "Access and manage your personal profile", category: "Core", isActive: true }, { featureId: 43, featureName: "Employee Projects", description: "Manage projects assigned to employees", category: "Project", isActive: true }, { featureId: 44, featureName: "Health Dashboard", description: "System and project health overview", category: "Management", isActive: true }, { featureId: 50, featureName: "Gantt Chart", description: "Visual project timeline and schedule", category: "Project", isActive: true }, { featureId: 51, featureName: "Resource Allocation", description: "Manage and track resource distribution", category: "Project", isActive: true }, // Asset Management features { featureId: 45, featureName: "Assets", description: "General asset management", category: "Asset Management", isActive: true }, { featureId: 46, featureName: "System Details", description: "System and hardware details for assets", category: "Asset Management", isActive: true }, { featureId: 47, featureName: "Asset Assignments", description: "Track asset assignments to employees", category: "Asset Management", isActive: true }, { featureId: 48, featureName: "My Asset Requests", description: "Employee interface for requesting assets", category: "Asset Management", isActive: true }, { featureId: 49, featureName: "Asset Request Management", description: "Admin interface for managing asset requests", category: "Asset Management", isActive: true }, // New Admin features { featureId: 52, featureName: "Feature Management", description: "System features and functionality management", category: "Administration", isActive: true }, { featureId: 53, featureName: "Role Permissions", description: "Manage permissions for system roles", category: "Administration", isActive: true }, ]; let createdCount = 0; for (const reqFeature of requiredFeatures) { const exists = existingFeatures.some(f => f.featureId === reqFeature.featureId); if (!exists) { console.log(`Creating missing feature: ${reqFeature.featureName}`); await featureApi.create(reqFeature); createdCount++; } } queryClient.invalidateQueries({ queryKey: ["features"] }); if (createdCount > 0) { toast.success(`Added ${createdCount} missing features`, { description: "All standard features have been added to the system." }); } else { toast.info("All features already exist", { description: "No new features were added." }); } } catch (error) { console.error("Error ensuring features:", error); toast.error("Failed to create features", { description: "An error occurred while creating the required features." }); } }; return (

Features

System features and functionality

!createMutation.isPending && setIsAddDialogOpen(false)} title="Create New Feature" description="Add a new feature to the system" allowClose={!createMutation.isPending} isPending={createMutation.isPending} >
setNewFeatureStatus(checked as boolean)} />
Feature Management {features?.length || 0} features defined in the system
setSearchQuery(e.target.value)} />
{isLoading ? (
) : error ? (

Error loading features. Please try again later.

) : filteredFeatures?.length === 0 ? (

No features found.

) : (
ID Feature Name Description Category Status Actions {filteredFeatures?.map((feature: Feature) => ( {feature.featureId} {editingFeature?.featureId === feature.featureId ? ( setEditFeatureName(e.target.value)} className="w-full" /> ) : ( {feature.featureName} )} {editingFeature?.featureId === feature.featureId ? ( setEditFeatureDescription(e.target.value)} className="w-full" /> ) : ( {feature.description || "-"} )} {editingFeature?.featureId === feature.featureId ? ( setEditFeatureCategory(e.target.value)} className="w-full" /> ) : ( {feature.category || "-"} )} {editingFeature?.featureId === feature.featureId ? (
setEditFeatureStatus(checked as boolean)} />
) : ( {feature.isActive ? "Active" : "Inactive"} )} {editingFeature?.featureId === feature.featureId ? (
) : (
)}
))}
)}
); }; export default Features;