(Feat-Fix): Type Fixes, sloppy import fixes, fix dynamic activity fetching and more

This commit is contained in:
2025-12-21 07:49:37 +00:00
parent 865e0bf00e
commit 6cc9ebdcf7
17 changed files with 96 additions and 78 deletions

View File

@@ -1,5 +1,6 @@
import React, { useState } from "react";
import { AuthProvider, useAuth } from "./contexts/AuthContext.tsx";
import { AuthProvider } from "./contexts/AuthContext.tsx";
import { useAuth } from "./contexts/authContext.ts";
import { Sidebar } from "./components/layout/Sidebar.tsx";
import { Header } from "./components/layout/Header.tsx";
import { DashboardPage } from "./pages/DashboardPage.tsx";

View File

@@ -15,7 +15,7 @@ import {
User,
X,
} from "lucide-react";
import { useAuth } from "../../contexts/AuthContext.tsx";
import { useAuth } from "../../contexts/authContext.ts";
import { useDepartments } from "../../hooks/useDepartments.ts";
import { api } from "../../services/api.ts";
import type { User as UserType } from "../../types.ts";
@@ -100,7 +100,7 @@ const ProfilePopup: React.FC<ProfilePopupProps> = (
<div className="bg-gradient-to-r from-teal-600 to-teal-500 px-6 py-4">
<div className="flex justify-between items-start">
<div className="flex-1" />
<button
<button type="button"
onClick={onClose}
className="text-white/80 hover:text-white hover:bg-white/20 rounded-full p-1 transition-colors"
>
@@ -167,7 +167,7 @@ const ProfilePopup: React.FC<ProfilePopupProps> = (
{/* Personal & Bank Details Section - for Employee and Contractor */}
{isEmployeeOrContractor && (
<button
<button type="button"
onClick={() => setShowDetails(!showDetails)}
className="w-full flex items-center justify-between p-3 bg-teal-50 hover:bg-teal-100 rounded-xl transition-colors"
>
@@ -277,7 +277,7 @@ const ProfilePopup: React.FC<ProfilePopupProps> = (
)}
{/* Permissions Section */}
<button
<button type="button"
onClick={() => setShowPermissions(!showPermissions)}
className="w-full flex items-center justify-between p-3 bg-amber-50 hover:bg-amber-100 rounded-xl transition-colors"
>
@@ -321,7 +321,7 @@ const ProfilePopup: React.FC<ProfilePopupProps> = (
{/* Sign Out Button */}
<div className="px-6 pb-4">
<button
<button type="button"
onClick={onLogout}
className="w-full flex items-center justify-center gap-2 px-4 py-3 bg-red-50 hover:bg-red-100 text-red-600 rounded-xl transition-colors font-medium"
>
@@ -351,12 +351,12 @@ export const Header: React.FC = () => {
</h1>
</div>
<div className="flex items-center space-x-4">
<button className="p-2 text-gray-600 hover:bg-gray-100 rounded-full relative">
<button type="button" className="p-2 text-gray-600 hover:bg-gray-100 rounded-full relative">
<Bell size={20} />
<span className="absolute top-1 right-1 w-2 h-2 bg-red-500 rounded-full">
</span>
</button>
<button
<button type="button"
onClick={() => setIsProfileOpen(!isProfileOpen)}
className="w-10 h-10 bg-teal-600 rounded-full flex items-center justify-center text-white font-medium hover:bg-teal-700"
>

View File

@@ -12,7 +12,7 @@ import {
Scale,
Users,
} from "lucide-react";
import { useAuth } from "../../contexts/AuthContext.tsx";
import { useAuth } from "../../contexts/authContext.ts";
interface SidebarItemProps {
icon: React.ElementType;
@@ -24,7 +24,7 @@ interface SidebarItemProps {
const SidebarItem: React.FC<SidebarItemProps> = (
{ icon: Icon, label, active, onClick },
) => (
<button
<button type="button"
onClick={onClick}
className={`w-full flex items-center space-x-3 px-6 py-4 cursor-pointer transition-colors duration-200 outline-none focus:outline-none ${
active

View File

@@ -3,9 +3,6 @@ import { api } from "../services/api.ts";
import type { User } from "../types.ts";
import { AuthContext } from "./authContext.ts";
// Re-export useAuth for convenience
export { useAuth } from "./authContext.ts";
interface AuthProviderProps {
children: ReactNode;
}

View File

@@ -1,5 +1,5 @@
import { createContext, useContext } from "react";
import type { User } from "../types";
import type { User } from "../types.ts";
export interface AuthContextType {
user: User | null;

View File

@@ -8,14 +8,18 @@ export const useActivities = (subDepartmentId?: string | number) => {
const [error, setError] = useState<string | null>(null);
const fetchActivities = useCallback(async () => {
// Don't fetch if no subDepartmentId - return empty array
if (!subDepartmentId) {
setActivities([]);
return;
}
setLoading(true);
setError(null);
try {
const params: { subDepartmentId?: number; departmentId?: number } = {};
if (subDepartmentId) {
params.subDepartmentId = Number(subDepartmentId);
}
const data = await api.getActivities(params);
const data = await api.getActivities({
subDepartmentId: Number(subDepartmentId),
});
setActivities(data);
} catch (err) {
setError(

View File

@@ -1,7 +1,7 @@
import React from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App";
import App from "./App.tsx";
createRoot(document.getElementById("root")!).render(
<React.StrictMode>

View File

@@ -19,7 +19,7 @@ import { Button } from "../components/ui/Button.tsx";
import { Input, Select } from "../components/ui/Input.tsx";
import { useDepartments, useSubDepartments } from "../hooks/useDepartments.ts";
import { useActivitiesByDepartment } from "../hooks/useActivities.ts";
import { useAuth } from "../contexts/AuthContext.tsx";
import { useAuth } from "../contexts/authContext.ts";
import { api } from "../services/api.ts";
import { Activity, SubDepartment } from "../types.ts";

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useState } from "react";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Calendar, Eye, Filter, RefreshCw, Search } from "lucide-react";
import { Card, CardContent } from "../components/ui/Card.tsx";
import {
@@ -13,7 +13,7 @@ import { Button } from "../components/ui/Button.tsx";
import { Input, Select } from "../components/ui/Input.tsx";
import { api } from "../services/api.ts";
import { useDepartments } from "../hooks/useDepartments.ts";
import { useAuth } from "../contexts/AuthContext.tsx";
import { useAuth } from "../contexts/authContext.ts";
export const AllRatesPage: React.FC = () => {
const { user } = useAuth();
@@ -41,7 +41,7 @@ export const AllRatesPage: React.FC = () => {
const isSuperAdmin = user?.role === "SuperAdmin";
// Fetch all rates
const fetchAllRates = async () => {
const fetchAllRates = useCallback(async () => {
setLoading(true);
setError("");
try {
@@ -60,13 +60,13 @@ export const AllRatesPage: React.FC = () => {
} finally {
setLoading(false);
}
};
}, [filters.departmentId, filters.startDate, filters.endDate]);
useEffect(() => {
if (isSuperAdmin) {
fetchAllRates();
}
}, [isSuperAdmin]);
}, [isSuperAdmin, fetchAllRates]);
const handleFilterChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>,
@@ -212,7 +212,7 @@ export const AllRatesPage: React.FC = () => {
<Button onClick={applyFilters} size="sm">
Apply Filters
</Button>
<Button variant="outline" onClick={clearFilters} size="sm">
<Button variant="primary" onClick={clearFilters} size="sm">
Clear
</Button>
</div>

View File

@@ -27,7 +27,7 @@ import { Button } from "../components/ui/Button.tsx";
import { Input, Select } from "../components/ui/Input.tsx";
import { api } from "../services/api.ts";
import { useEmployees } from "../hooks/useEmployees.ts";
import { useAuth } from "../contexts/AuthContext.tsx";
import { useAuth } from "../contexts/authContext.ts";
import type { AttendanceStatus } from "../types.ts";
export const AttendancePage: React.FC = () => {

View File

@@ -26,7 +26,7 @@ import { Card, CardContent, CardHeader } from "../components/ui/Card.tsx";
import { useEmployees } from "../hooks/useEmployees.ts";
import { useDepartments } from "../hooks/useDepartments.ts";
import { useWorkAllocations } from "../hooks/useWorkAllocations.ts";
import { useAuth } from "../contexts/AuthContext.tsx";
import { useAuth } from "../contexts/authContext.ts";
import { api } from "../services/api.ts";
// Types for attendance hierarchy
@@ -260,8 +260,12 @@ export const DashboardPage: React.FC = () => {
? "Present"
: "Absent")
: undefined,
inTime: empAttendance?.check_in_time?.substring(0, 5),
outTime: empAttendance?.check_out_time?.substring(0, 5),
inTime: empAttendance?.check_in_time
? new Date(empAttendance.check_in_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
: undefined,
outTime: empAttendance?.check_out_time
? new Date(empAttendance.check_out_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
: undefined,
remark: empAttendance?.remark,
children: [],
};
@@ -298,8 +302,12 @@ export const DashboardPage: React.FC = () => {
? "Present"
: "Absent")
: undefined,
inTime: empAttendance?.check_in_time?.substring(0, 5),
outTime: empAttendance?.check_out_time?.substring(0, 5),
inTime: empAttendance?.check_in_time
? new Date(empAttendance.check_in_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
: undefined,
outTime: empAttendance?.check_out_time
? new Date(empAttendance.check_out_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
: undefined,
remark: empAttendance?.remark,
children: [],
};
@@ -369,8 +377,12 @@ export const DashboardPage: React.FC = () => {
? "Present"
: "Absent")
: undefined,
inTime: empAttendance?.check_in_time?.substring(0, 5),
outTime: empAttendance?.check_out_time?.substring(0, 5),
inTime: empAttendance?.check_in_time
? new Date(empAttendance.check_in_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
: undefined,
outTime: empAttendance?.check_out_time
? new Date(empAttendance.check_out_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
: undefined,
remark: empAttendance?.remark,
children: [],
};
@@ -408,8 +420,12 @@ export const DashboardPage: React.FC = () => {
? "Present"
: "Absent")
: undefined,
inTime: empAttendance?.check_in_time?.substring(0, 5),
outTime: empAttendance?.check_out_time?.substring(0, 5),
inTime: empAttendance?.check_in_time
? new Date(empAttendance.check_in_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
: undefined,
outTime: empAttendance?.check_out_time
? new Date(empAttendance.check_out_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
: undefined,
remark: empAttendance?.remark,
children: [],
};
@@ -599,8 +615,8 @@ export const DashboardPage: React.FC = () => {
</span>
)}
</td>
<td className="py-3 px-4 text-gray-600">{node.inTime || "-"}</td>
<td className="py-3 px-4 text-gray-600">{node.outTime || "-"}</td>
<td className="py-3 px-4 text-gray-600 whitespace-nowrap">{node.inTime || "-"}</td>
<td className="py-3 px-4 text-gray-600 whitespace-nowrap">{node.outTime || "-"}</td>
<td className="py-3 px-4 text-gray-500 text-sm">
{node.remark || "-"}
</td>
@@ -666,28 +682,28 @@ export const DashboardPage: React.FC = () => {
<table className="w-full">
<thead>
<tr className="bg-gray-50 border-b border-gray-200">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm min-w-[200px]">
Level / Name
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Dept
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Sub-Dept
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Activity
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Status
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap min-w-[120px]">
In Time
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap min-w-[120px]">
Out Time
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Remark
</th>
</tr>
@@ -1018,31 +1034,31 @@ export const DashboardPage: React.FC = () => {
<table className="w-full">
<thead>
<tr className="bg-gray-50 border-b border-gray-200">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm min-w-[200px]">
Contractor / Employee
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Dept
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Sub-Dept
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Activity
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Rate ()
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Status
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap min-w-[120px]">
In Time
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap min-w-[120px]">
Out Time
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Remark
</th>
</tr>
@@ -1162,10 +1178,10 @@ export const DashboardPage: React.FC = () => {
</span>
)}
</td>
<td className="py-3 px-4 text-sm text-gray-600">
<td className="py-3 px-4 text-sm text-gray-600 whitespace-nowrap">
{emp.inTime || "-"}
</td>
<td className="py-3 px-4 text-sm text-gray-600">
<td className="py-3 px-4 text-sm text-gray-600 whitespace-nowrap">
{emp.outTime || "-"}
</td>
<td className="py-3 px-4 text-sm text-gray-500">
@@ -1651,19 +1667,19 @@ export const DashboardPage: React.FC = () => {
<table className="w-full">
<thead>
<tr className="bg-gray-50 border-b border-gray-200">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm min-w-[150px]">
Employee
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Today's Status
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap min-w-[120px]">
Check In
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap min-w-[120px]">
Check Out
</th>
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm">
<th className="text-left py-3 px-4 font-semibold text-gray-600 text-sm whitespace-nowrap">
Current Work
</th>
</tr>
@@ -1716,13 +1732,13 @@ export const DashboardPage: React.FC = () => {
: empAttendance?.status || "Absent"}
</span>
</td>
<td className="py-3 px-4 text-sm text-gray-600">
<td className="py-3 px-4 text-sm text-gray-600 whitespace-nowrap">
{empAttendance?.check_in_time
? new Date(empAttendance.check_in_time)
.toLocaleTimeString()
: "-"}
</td>
<td className="py-3 px-4 text-sm text-gray-600">
<td className="py-3 px-4 text-sm text-gray-600 whitespace-nowrap">
{empAttendance?.check_out_time
? new Date(empAttendance.check_out_time)
.toLocaleTimeString()

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react";
import { useAuth } from "../contexts/AuthContext.tsx";
import { useAuth } from "../contexts/authContext.ts";
import {
ArrowRight,
CheckCircle,
@@ -268,7 +268,7 @@ export const LoginPage: React.FC = () => {
{/* Modal */}
<div className="relative bg-slate-800/90 backdrop-blur-xl rounded-2xl shadow-2xl p-8 w-full max-w-md border border-white/10 animate-in fade-in zoom-in duration-200">
{/* Close button */}
<button
<button type="button"
onClick={closeForgotModal}
className="absolute top-4 right-4 text-gray-400 hover:text-white transition-colors"
>
@@ -336,7 +336,7 @@ export const LoginPage: React.FC = () => {
</form>
{/* Back to login */}
<button
<button type="button"
onClick={closeForgotModal}
className="w-full mt-4 text-gray-400 hover:text-white text-sm transition-colors"
>
@@ -359,7 +359,7 @@ export const LoginPage: React.FC = () => {
{forgotEmail}
</span>
</p>
<button
<button type="button"
onClick={closeForgotModal}
className="w-full bg-gradient-to-r from-green-500 to-emerald-600 hover:from-green-600 hover:to-emerald-700 text-white font-semibold py-4 rounded-xl shadow-lg transition-all duration-300"
>

View File

@@ -14,7 +14,7 @@ import { Input, Select } from "../components/ui/Input.tsx";
import { api } from "../services/api.ts";
import { useDepartments, useSubDepartments } from "../hooks/useDepartments.ts";
import { useActivities } from "../hooks/useActivities.ts";
import { useAuth } from "../contexts/AuthContext.tsx";
import { useAuth } from "../contexts/authContext.ts";
export const RatesPage: React.FC = () => {
const [activeTab, setActiveTab] = useState<"list" | "add">("list");

View File

@@ -19,7 +19,7 @@ import { Button } from "../components/ui/Button.tsx";
import { Input, Select } from "../components/ui/Input.tsx";
import { api } from "../services/api.ts";
import { useDepartments } from "../hooks/useDepartments.ts";
import { useAuth } from "../contexts/AuthContext.tsx";
import { useAuth } from "../contexts/authContext.ts";
import {
exportAllocationsToXLSX,
exportWorkReportToXLSX,

View File

@@ -22,7 +22,7 @@ import { Input, Select } from "../components/ui/Input.tsx";
import { api } from "../services/api.ts";
import { useDepartments, useSubDepartments } from "../hooks/useDepartments.ts";
import { useActivities } from "../hooks/useActivities.ts";
import { useAuth } from "../contexts/AuthContext.tsx";
import { useAuth } from "../contexts/authContext.ts";
export const StandardRatesPage: React.FC = () => {
const [activeTab, setActiveTab] = useState<"list" | "add" | "compare">(

View File

@@ -23,7 +23,7 @@ import { Button } from "../components/ui/Button.tsx";
import { Input, PasswordInput, Select } from "../components/ui/Input.tsx";
import { useEmployees } from "../hooks/useEmployees.ts";
import { useDepartments } from "../hooks/useDepartments.ts";
import { useAuth } from "../contexts/AuthContext.tsx";
import { useAuth } from "../contexts/authContext.ts";
import { api } from "../services/api.ts";
export const UsersPage: React.FC = () => {

View File

@@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react";
import { CheckCircle, Plus, RefreshCw, Search, Trash2 } from "lucide-react";
import { Card, CardContent } from "../components/ui/Card";
import { Card, CardContent } from "../components/ui/Card.tsx";
import {
Table,
TableBody,
@@ -15,7 +15,7 @@ import { useWorkAllocations } from "../hooks/useWorkAllocations.ts";
import { useDepartments, useSubDepartments } from "../hooks/useDepartments.ts";
import { useEmployees } from "../hooks/useEmployees.ts";
import { useActivities } from "../hooks/useActivities.ts";
import { useAuth } from "../contexts/AuthContext.tsx";
import { useAuth } from "../contexts/authContext.ts";
import { api } from "../services/api.ts";
export const WorkAllocationPage: React.FC = () => {
@@ -227,7 +227,7 @@ export const WorkAllocationPage: React.FC = () => {
<div className="border-b border-gray-200">
<div className="flex space-x-8 px-6">
{["create", "view", "summary"].map((tab) => (
<button
<button type="button"
key={tab}
onClick={() => setActiveTab(tab as any)}
className={`py-4 px-2 border-b-2 font-medium text-sm ${
@@ -448,10 +448,10 @@ export const WorkAllocationPage: React.FC = () => {
</div>
<div className="flex justify-end gap-4 mt-6">
<Button variant="outline" onClick={() => setActiveTab("view")}>
<Button variant="primary" onClick={() => setActiveTab("view")}>
Cancel
</Button>
<Button onClick={handleCreateAllocation} disabled={formLoading}>
<Button variant="primary" onClick={handleCreateAllocation} disabled={formLoading}>
{formLoading ? "Creating..." : (
<>
<Plus size={16} className="mr-2" />