diff --git a/apps/frontend/src/components/ApplicationTable.test.tsx b/apps/frontend/src/components/ApplicationTable.test.tsx
index 6d6c3d7ca..4c406713f 100644
--- a/apps/frontend/src/components/ApplicationTable.test.tsx
+++ b/apps/frontend/src/components/ApplicationTable.test.tsx
@@ -1,6 +1,7 @@
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import { ChakraProvider, defaultSystem } from '@chakra-ui/react';
+import { MemoryRouter } from 'react-router-dom';
import ApplicationTable from './ApplicationTable';
import type { ApplicationRow } from '@hooks/useApplications';
import {
@@ -9,7 +10,11 @@ import {
} from '@utils/applicationFilters';
function renderWithChakra(ui: React.ReactElement) {
- return render({ui});
+ return render(
+
+ {ui}
+ ,
+ );
}
const mockApplications: ApplicationRow[] = [
diff --git a/apps/frontend/src/components/ApplicationTable.tsx b/apps/frontend/src/components/ApplicationTable.tsx
index b54caca81..2ee054630 100644
--- a/apps/frontend/src/components/ApplicationTable.tsx
+++ b/apps/frontend/src/components/ApplicationTable.tsx
@@ -1,13 +1,17 @@
-import { useMemo } from 'react';
-import { Table } from '@chakra-ui/react';
+import { useEffect, useMemo, useState } from 'react';
+import { Flex, Input, InputGroup, Spacer, Table } from '@chakra-ui/react';
import type { ApplicationRow } from '@hooks/useApplications';
import StatusPill, { StatusPillConfig, StatusVariant } from './StatusPill';
import {
compileApplicationFilterPredicate,
compileApplicationSearchPredicate,
EMPTY_APPLICATION_FILTERS,
+ normalizeDateToDay,
type ApplicationFilters,
} from '@utils/applicationFilters';
+import apiClient from '@api/apiClient';
+import { MdEdit } from 'react-icons/md';
+import { useNavigate } from 'react-router-dom';
const COLUMNS = [
'Name',
@@ -67,6 +71,11 @@ export function ApplicationTable({
searchQuery = '',
filters = EMPTY_APPLICATION_FILTERS,
}: ApplicationTableProps) {
+ const navigate = useNavigate();
+ const [actualStartDates, setActualStartDates] = useState<
+ Record
+ >({});
+ const [editingIds, setEditingIds] = useState>(new Set());
const matchesStructuredFilters = useMemo(
() => compileApplicationFilterPredicate(filters),
[filters],
@@ -77,6 +86,19 @@ export function ApplicationTable({
[searchQuery],
);
+ useEffect(() => {
+ setActualStartDates((prev) => {
+ const next = { ...prev };
+ applications.forEach((application) => {
+ if (next[application.appId] === undefined) {
+ next[application.appId] =
+ normalizeDateToDay(application.actualStartDate) ?? '';
+ }
+ });
+ return next;
+ });
+ }, [applications]);
+
const filteredApplications = useMemo(
() =>
applications.filter((application) => {
@@ -88,6 +110,19 @@ export function ApplicationTable({
[applications, matchesSearchQuery, matchesStructuredFilters],
);
+ const handleActualStartDateUpdate = async (
+ nextDate: string,
+ application: ApplicationRow,
+ ) => {
+ if (!application) return;
+ const updatedApplication = await apiClient.updateApplicationActualStartDate(
+ application.appId,
+ nextDate,
+ );
+ // setApplicationsState(updatedApplication); TODO
+ console.log('we clicked the button!');
+ };
+
return (
@@ -104,38 +139,102 @@ export function ApplicationTable({
- {filteredApplications.map((application) => (
-
-
- {
+ const isEditingActualStart = editingIds.has(application.appId);
+
+ return (
+
+ navigate(`/admin/view-application/${application.appId}`)
+ }
+ transition="background-color 240ms ease-in-out"
+ _hover={{
+ backgroundColor: '#DBEAFE',
+ '& > td': {
+ backgroundColor: '#DBEAFE',
+ transition: 'background-color 240ms ease-in-out',
+ },
+ }}
+ >
+ {titleCaseName(application.name)}
+
+ {formatDate(application.proposedStartDate)}
+
+ {
+ if (isEditingActualStart) {
+ event.stopPropagation();
+ }
+ }}
>
- {titleCaseName(application.name)}
-
-
- {formatDate(application.proposedStartDate)}
- {formatDate(application.actualStartDate)}
-
- {formatDesiredExperience(application.desiredExperience)}
-
- {application.applicantType}
- {application.discipline}
-
- {titleCaseName(application.disciplineAdminName)}
-
-
- {StatusPillConfig[application.status as StatusVariant] ? (
-
- {StatusPillConfig[application.status as StatusVariant].label}
-
- ) : (
- application.status
- )}
-
-
- ))}
+
+ {isEditingActualStart ? (
+
+ {
+ event.stopPropagation();
+ const value = event.target.value;
+ setActualStartDates((prev) => ({
+ ...prev,
+ [application.appId]: value,
+ }));
+ }}
+ />
+
+ ) : (
+ formatDate(actualStartDates[application.appId])
+ )}
+
+ {
+ event.stopPropagation();
+ if (editingIds.has(application.appId)) {
+ handleActualStartDateUpdate(
+ actualStartDates[application.appId] ?? '',
+ application,
+ );
+
+ setEditingIds((prev) => {
+ const next = new Set(prev);
+ next.delete(application.appId);
+ return next;
+ });
+ } else {
+ setEditingIds((prev) =>
+ new Set(prev).add(application.appId),
+ );
+ }
+ }}
+ />
+
+
+
+ {formatDesiredExperience(application.desiredExperience)}
+
+ {application.applicantType}
+ {application.discipline}
+
+ {titleCaseName(application.disciplineAdminName)}
+
+
+ {StatusPillConfig[application.status as StatusVariant] ? (
+
+ {
+ StatusPillConfig[application.status as StatusVariant]
+ .label
+ }
+
+ ) : (
+ application.status
+ )}
+
+
+ );
+ })}
);