Wrapped up discharge form close #159

This commit is contained in:
2026-01-28 15:39:45 -05:00
parent c646254616
commit 22eaba6f90
8 changed files with 111 additions and 25 deletions

View File

@@ -1,3 +1,4 @@
import { Discharge } from "@shared/schemas/dischargeSchema";
import { memberSettings, Member, MemberLight, MemberCardDetails, PaginatedMembers } from "@shared/types/member";
// @ts-ignore
@@ -13,14 +14,14 @@ export async function getMembers(): Promise<Member[]> {
return response.json();
}
export async function getMembersFiltered(params: {
page?: number;
pageSize?: number;
search?: string;
status?: string;
unitId?: string;
export async function getMembersFiltered(params: {
page?: number;
pageSize?: number;
search?: string;
status?: string;
unitId?: string;
} = {}): Promise<PaginatedMembers> {
// Construct the query string dynamically
const query = new URLSearchParams();
if (params.page) query.append('page', params.page.toString());
@@ -114,4 +115,24 @@ export async function getFullMembers(ids: number[]): Promise<MemberCardDetails[]
throw new Error("Failed to fetch settings");
}
return response.json();
}
/**
* Requests for the given member to be discharged
* @param data discharge packet
* @returns true on success
*/
export async function dischargeMember(data: Discharge): Promise<boolean> {
const response = await fetch(`${addr}/members/discharge`, {
credentials: 'include',
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error("Failed to discharge member");
}
return true;
}

View File

@@ -18,8 +18,9 @@ import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
import MemberCard from './MemberCard.vue'
import { Member } from '@shared/types/member'
import { Discharge, dischargeSchema } from '@shared/schemas/dischargeSchema';
import { dischargeMember } from '@/api/member'
// 1. Props for control and data
const props = defineProps<{
open: boolean
member: Member | null
@@ -27,18 +28,17 @@ const props = defineProps<{
const emit = defineEmits(['update:open', 'discharged'])
// 2. Discharge-specific schema
const formSchema = toTypedSchema(z.object({
reason: z.string().min(1, "Please provide a valid reason for discharge").max(200),
effectiveDate: z.string().min(1, "Date is required"),
}))
const formSchema = toTypedSchema(dischargeSchema);
function onSubmit(values: any) {
async function onSubmit(values: z.infer<typeof dischargeSchema>) {
const data: Discharge = { userID: props.member.member_id, reason: values.reason }
console.log('Discharging member:', props.member?.member_id)
console.log('Discharge Data:', values)
console.log('Discharge Data:', data)
await dischargeMember(data);
// Notify parent to refresh/close
emit('discharged', { memberId: props.member?.member_id, ...values })
emit('discharged', { data })
emit('update:open', false)
}
</script>
@@ -62,19 +62,19 @@ function onSubmit(values: any) {
<VeeField v-slot="{ componentField, errors }" name="reason">
<Field :data-invalid="!!errors.length">
<FieldLabel>Reason for Discharge</FieldLabel>
<Textarea placeholder="Retirement, inactivity, etc. "
v-bind="componentField" class="resize-none" />
<Textarea placeholder="Retirement, inactivity, etc. " v-bind="componentField"
class="resize-none" />
<FieldError v-if="errors.length" :errors="errors" />
</Field>
</VeeField>
<VeeField v-slot="{ componentField, errors }" name="effectiveDate">
<!-- <VeeField v-slot="{ componentField, errors }" name="effectiveDate">
<Field :data-invalid="!!errors.length">
<FieldLabel>Effective Date</FieldLabel>
<Input type="date" v-bind="componentField" />
<FieldError v-if="errors.length" :errors="errors" />
</Field>
</VeeField>
</VeeField> -->
</form>
</Form>

View File

@@ -140,8 +140,7 @@ function openDischargeModal(member) {
}
function handleDischargeSuccess(data) {
// Refresh your list or show a toast
console.log('Member removed from list:', data.memberId)
fetchMembers();
}
</script>