assigment and reports groundwork

This commit is contained in:
dimitar committed 2026-03-19 04:36:35 +01:00
1 parent 74f0d0dbed
commit 06973ccfb2
9 files changed
+299 -49

No files matched your search

@@ -35,22 +35,18 @@ export async function DELETE(
const { id } = await params;
// Get all assignments for the trainer to find the one with this ID
// Note: We need to find the assignment ID, not the trainer or client ID
// For now, we'll deactivate by finding the assignment through the trainer
// This is a simplified approach - in production you'd want a direct getById method
// Try to find the assignment by checking trainer's assignments first
const trainerAssignments = await db.getTrainerClientAssignments(
currentUser.id,
);
const assignment = trainerAssignments.find((a) => a.id === id);
let assignment = trainerAssignments.find((a) => a.id === id);
if (!assignment) {
// Check if any trainer has this assignment
const allAssignments = await db.getTrainerClientAssignments("");
const foundAssignment = allAssignments.find((a) => a.id === id);
// Check all assignments to find the one with this ID
const allAssignments = await db.getAllTrainerClientAssignments();
assignment = allAssignments.find((a) => a.id === id);
if (!foundAssignment) {
if (!assignment) {
return NextResponse.json(
{ error: "Assignment not found" },
{ status: 404 },
@@ -48,8 +48,7 @@ export async function GET(request: NextRequest) {
}
} else {
// Get all assignments (for admins, filtered by gym)
assignments = await db.getTrainerClientAssignments("");
// TODO: Filter by gym once gymId is properly set
assignments = await db.getAllTrainerClientAssignments();
}
return NextResponse.json({ assignments });
+20 -2
View File
@@ -45,12 +45,24 @@ export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const role = searchParams.get("role");
log.debug("User API called", {
currentUserId: currentUser.id,
currentUserRole: currentUser.role,
currentUserGymId: currentUser.gymId,
});
// Get target gym based on role
const targetGymId =
currentUser.role === "superAdmin"
? (searchParams.get("gymId") ?? undefined)
: (currentUser.gymId ?? undefined);
log.debug("Target gym calculation", {
targetGymId,
currentUserRole: currentUser.role,
currentUserGymId: currentUser.gymId,
});
// Validate gym access for non-superAdmins
if (currentUser.role !== "superAdmin" && !targetGymId) {
return forbiddenResponse("No gym assigned");
@@ -61,6 +73,12 @@ export async function GET(request: NextRequest) {
? await getUsersByGym(targetGymId)
: await db.getAllUsers();
log.debug("Users fetched from database", {
targetGymId,
totalUsers: Array.isArray(users) ? users.length : 0,
sampleGymId: users && users[0] ? (users[0] as any).gymId : null,
});
// Hydrate gymId from raw DB to ensure consistency with writes
const rawUserRows = await rawDb.all(sql`SELECT id, gym_id FROM users`);
const gymById = new Map<string, string | null>(
@@ -90,12 +108,12 @@ export async function GET(request: NextRequest) {
log.debug("Applied role filter", {
role,
usersAfterFilter: Array.isArray(users) ? users.length : 0,
sample:
sampleUser:
users && users[0]
? {
id: users[0].id,
role: users[0].role,
gymId: (users as any)[0].gymId,
gymId: (users[0] as any).gymId,
}
: null,
});
+27 -33
View File
@@ -12,7 +12,7 @@ import {
SelectValue,
} from "@/components/ui/select";
import { Badge } from "@/components/ui/badge";
import { Plus, Trash2, UserCheck, UserX } from "lucide-react";
import { Plus, UserCheck, UserX } from "lucide-react";
export default function TrainerClientsPage() {
const [trainers, setTrainers] = useState<User[]>([]);
@@ -32,37 +32,34 @@ export default function TrainerClientsPage() {
try {
setLoading(true);
// Fetch trainers
const trainersRes = await fetch("/api/users?role=trainer");
if (trainersRes.ok) {
const trainersData = await trainersRes.json();
setTrainers(trainersData.users || []);
}
const [trainersRes, clientsRes, assignmentsRes] = await Promise.all([
fetch("/api/users?role=trainer"),
fetch("/api/users?role=client"),
fetch("/api/trainer-client"),
]);
// Fetch clients
const clientsRes = await fetch("/api/users?role=client");
if (clientsRes.ok) {
const clientsData = await clientsRes.json();
setClients(clientsData.users || []);
}
const fetchedTrainers: User[] = trainersRes.ok
? (await trainersRes.json()).data?.users || []
: [];
const fetchedClients: User[] = clientsRes.ok
? (await clientsRes.json()).data?.users || []
: [];
setTrainers(fetchedTrainers);
setClients(fetchedClients);
// Fetch all assignments
const assignmentsRes = await fetch("/api/trainer-client");
if (assignmentsRes.ok) {
const assignmentsData = await assignmentsRes.json();
// Enrich assignments with user data
const enrichedAssignments = await Promise.all(
(assignmentsData.assignments || []).map(
async (assignment: TrainerClientAssignment) => {
const trainer = trainers.find(
(t: User) => t.id === assignment.trainerId,
);
const client = clients.find(
(c: User) => c.id === assignment.clientId,
);
return { ...assignment, trainer, client };
},
),
const enrichedAssignments = (assignmentsData.assignments || []).map(
(assignment: TrainerClientAssignment) => {
return {
...assignment,
trainer: fetchedTrainers.find(
(t) => t.id === assignment.trainerId,
),
client: fetchedClients.find((c) => c.id === assignment.clientId),
};
},
);
setAssignments(enrichedAssignments);
}
@@ -93,7 +90,7 @@ export default function TrainerClientsPage() {
alert("Assignment created successfully!");
setSelectedTrainer("");
setSelectedClient("");
fetchData(); // Refresh
fetchData();
} else {
const error = await response.json();
alert(error.error || "Failed to create assignment");
@@ -116,7 +113,7 @@ export default function TrainerClientsPage() {
if (response.ok) {
alert("Assignment removed successfully!");
fetchData(); // Refresh
fetchData();
} else {
const error = await response.json();
alert(error.error || "Failed to remove assignment");
@@ -151,7 +148,6 @@ export default function TrainerClientsPage() {
</h1>
</div>
{/* Create Assignment Form */}
<Card>
<CardHeader>
<CardTitle>Assign Trainer to Client</CardTitle>
@@ -206,7 +202,6 @@ export default function TrainerClientsPage() {
</CardContent>
</Card>
{/* Active Assignments */}
<Card>
<CardHeader>
<div className="flex justify-between items-center">
@@ -260,7 +255,6 @@ export default function TrainerClientsPage() {
</CardContent>
</Card>
{/* Inactive Assignments */}
{getInactiveAssignments().length > 0 && (
<Card>
<CardHeader>