diff --git a/api/index.js b/api/index.js index 91318fe..de25f24 100644 --- a/api/index.js +++ b/api/index.js @@ -50,7 +50,11 @@ app.get('/application/me', async (req, res) => { const applicationId = 1; const rows = await pool.query( - 'SELECT * FROM applications WHERE id = ?', + `SELECT app.*, + member.name AS member_name + FROM applications AS app + INNER JOIN members AS member ON member.id = app.member_id + WHERE app.member_id = ?;`, [applicationId] ); @@ -65,6 +69,29 @@ app.get('/application/me', async (req, res) => { } }); +app.get('/application/:id', async (req, res) => { + const appID = req.params.id; + try { + const rows = await pool.query( + `SELECT app.*, + member.name AS member_name + FROM applications AS app + INNER JOIN members AS member ON member.id = app.member_id + WHERE app.id = 1;`, + [appID] + ); + + if (!Array.isArray(rows) || rows.length === 0) { + return res.send(404).json("Application Not Found"); + } + + return res.status(200).json(rows[0]); + } + catch (err) { + console.error('Query failed:', err); + return res.status(500).json({ error: 'Failed to load application' }); + } +}) app.get('/application/all', async (req, res) => { try { diff --git a/ui/src/api/application.ts b/ui/src/api/application.ts index f1cf09f..2b690d4 100644 --- a/ui/src/api/application.ts +++ b/ui/src/api/application.ts @@ -15,10 +15,44 @@ export type ApplicationDto = Partial<{ aknowledgeRules: boolean }> -type ApplicationFull = Partial<{ - app: ApplicationDto, - messages: object[] -}> +export interface ApplicationData { + dob: string; + name: string; + playtime: number; + hobbies: string; + military: boolean; + communities: string; + joinReason: string; + milsimAttraction: string; + referral: string; + steamProfile: string; + timezone: string; + canAttendSaturday: boolean; + interests: string; + aknowledgeRules: boolean; +} + +export interface ApplicationRow { + id: number; + member_id: number; + app_version: number; + app_data: ApplicationData; + + submitted_at: string; // ISO datetime from DB (e.g., "2025-08-25T18:04:29.000Z") + updated_at: string | null; + approved_at: string | null; + denied_at: string | null; + + app_status: Status; // generated column + decision_at: string | null; // generated column + + // present when you join members (e.g., SELECT a.*, m.name AS member_name) + member_name: string; +} + +export type ApplicationFull = ApplicationRow & { + messages?: object[]; +}; export enum Status { Pending = "Pending", @@ -68,7 +102,7 @@ export async function getAllApplications() { const res = await fetch(`http://${addr}/application/all`) if (res.ok) { - return await res.json(); + return res.json() } else { console.error("Something went wrong approving the application") } diff --git a/ui/src/components/application/ApplicationForm.vue b/ui/src/components/application/ApplicationForm.vue index f3e86e9..039cacf 100644 --- a/ui/src/components/application/ApplicationForm.vue +++ b/ui/src/components/application/ApplicationForm.vue @@ -16,6 +16,7 @@ import { Form } from 'vee-validate'; import { onMounted, ref } from 'vue'; import * as z from 'zod'; import DateInput from '../form/DateInput.vue'; +import { ApplicationData } from '@/api/application'; const formSchema = toTypedSchema(z.object({ dob: z.string().refine(v => v, { message: "A date of birth is required." }), @@ -45,7 +46,7 @@ const fallbackInitials = { const props = defineProps<{ readOnly: boolean, - data: object, + data: ApplicationData, }>() const emit = defineEmits(['submit']); @@ -57,8 +58,8 @@ async function onSubmit(val: any) { } onMounted(() => { - if (props.data) { - initialValues.value = { ...props.data, ...fallbackInitials } + if (props.data !== null) { + initialValues.value = { ...props.data } } else { initialValues.value = { ...fallbackInitials } } diff --git a/ui/src/pages/Application.vue b/ui/src/pages/Application.vue index 69b93f4..2d1118b 100644 --- a/ui/src/pages/Application.vue +++ b/ui/src/pages/Application.vue @@ -2,43 +2,58 @@ import ApplicationChat from '@/components/application/ApplicationChat.vue'; import ApplicationForm from '@/components/application/ApplicationForm.vue'; import { onMounted, ref } from 'vue'; -import { loadApplication, postApplication, postChatMessage, Status } from '@/api/application'; +import { ApplicationData, loadApplication, postApplication, postChatMessage, Status } from '@/api/application'; -const appData = ref | null>(null); +const appData = ref(null); const chatData = ref([]) const readOnly = ref(false); const newApp = ref(true); -const status = ref(Status.Pending); - +const status = ref(null); +const decisionDate = ref(null); +const submitDate = ref(null); +const loading = ref(true); +const member_name = ref(); onMounted(async () => { try { const data = await loadApplication() + console.log(data); if (data) { - appData.value = data.app; + appData.value = data.app_data; chatData.value = data.messages; + status.value = data.app_status; + decisionDate.value = new Date(data.decision_at); + submitDate.value = data.decision_at ? new Date(data.submitted_at) : null; + member_name.value = data.member_name; readOnly.value = true; } else { - appData.value = {} + appData.value = null newApp.value = false; } } catch (e) { console.error(e) } + loading.value = false; })