finalized application acceptance system and started making types shared across front and backend
This commit is contained in:
@@ -32,6 +32,7 @@ export interface ApplicationData {
|
||||
aknowledgeRules: boolean;
|
||||
}
|
||||
|
||||
//reflects how applications are stored in the database
|
||||
export interface ApplicationRow {
|
||||
id: number;
|
||||
member_id: number;
|
||||
@@ -43,7 +44,7 @@ export interface ApplicationRow {
|
||||
approved_at: string | null;
|
||||
denied_at: string | null;
|
||||
|
||||
app_status: Status; // generated column
|
||||
app_status: ApplicationStatus; // generated column
|
||||
decision_at: string | null; // generated column
|
||||
|
||||
// present when you join members (e.g., SELECT a.*, m.name AS member_name)
|
||||
@@ -64,7 +65,7 @@ export interface ApplicationFull {
|
||||
}
|
||||
|
||||
|
||||
export enum Status {
|
||||
export enum ApplicationStatus {
|
||||
Pending = "Pending",
|
||||
Accepted = "Accepted",
|
||||
Denied = "Denied",
|
||||
@@ -90,6 +91,7 @@ export async function postApplication(val: any) {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(out),
|
||||
credentials: 'include',
|
||||
})
|
||||
return res;
|
||||
}
|
||||
@@ -109,7 +111,7 @@ export async function postChatMessage(message: any, post_id: number) {
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
export async function getAllApplications() {
|
||||
export async function getAllApplications(): Promise<ApplicationFull> {
|
||||
const res = await fetch(`${addr}/application/all`)
|
||||
|
||||
if (res.ok) {
|
||||
|
||||
@@ -59,9 +59,13 @@ async function onSubmit(val: any) {
|
||||
|
||||
onMounted(() => {
|
||||
if (props.data !== null) {
|
||||
initialValues.value = { ...props.data }
|
||||
const parsed = typeof props.data === "string"
|
||||
? JSON.parse(props.data)
|
||||
: props.data;
|
||||
|
||||
initialValues.value = { ...parsed };
|
||||
} else {
|
||||
initialValues.value = { ...fallbackInitials }
|
||||
initialValues.value = { ...fallbackInitials };
|
||||
}
|
||||
})
|
||||
|
||||
@@ -76,8 +80,7 @@ onMounted(() => {
|
||||
<FormItem>
|
||||
<FormLabel>What is your date of birth?</FormLabel>
|
||||
<FormControl>
|
||||
<DateInput :model-value="(value as string) ?? ''" :disabled="readOnly"
|
||||
@update:model-value="handleChange" />
|
||||
<DateInput :model-value="(value as string) ?? ''" :disabled="readOnly" @update:model-value="handleChange" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import ApplicationChat from '@/components/application/ApplicationChat.vue';
|
||||
import ApplicationForm from '@/components/application/ApplicationForm.vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { ApplicationData, approveApplication, denyApplication, loadApplication, postApplication, postChatMessage, Status } from '@/api/application';
|
||||
import { ApplicationData, approveApplication, denyApplication, loadApplication, postApplication, postChatMessage, ApplicationStatus } from '@/api/application';
|
||||
import { useRoute } from 'vue-router';
|
||||
import Button from '@/components/ui/button/Button.vue';
|
||||
import { CheckIcon, XIcon } from 'lucide-vue-next';
|
||||
@@ -12,7 +12,7 @@ const appID = ref<number | null>(null);
|
||||
const chatData = ref<object[]>([])
|
||||
const readOnly = ref<boolean>(false);
|
||||
const newApp = ref<boolean>(null);
|
||||
const status = ref<Status>(null);
|
||||
const status = ref<ApplicationStatus>(null);
|
||||
const decisionDate = ref<Date | null>(null);
|
||||
const submitDate = ref<Date | null>(null);
|
||||
const loading = ref<boolean>(true);
|
||||
@@ -54,6 +54,7 @@ async function postComment(comment) {
|
||||
}
|
||||
|
||||
async function postApp(appData) {
|
||||
console.log("test")
|
||||
const res = await postApplication(appData);
|
||||
if (res.ok) {
|
||||
readOnly.value = true;
|
||||
@@ -89,11 +90,11 @@ async function handleDeny(id) {
|
||||
<div>
|
||||
<h3 class="text-right" :class="[
|
||||
'font-semibold',
|
||||
status === Status.Pending && 'text-yellow-500',
|
||||
status === Status.Accepted && 'text-green-500',
|
||||
status === Status.Denied && 'text-red-500'
|
||||
status === ApplicationStatus.Pending && 'text-yellow-500',
|
||||
status === ApplicationStatus.Accepted && 'text-green-500',
|
||||
status === ApplicationStatus.Denied && 'text-red-500'
|
||||
]">{{ status }}</h3>
|
||||
<p v-if="status != Status.Pending" class="text-muted-foreground">{{ status }}: {{
|
||||
<p v-if="status != ApplicationStatus.Pending" class="text-muted-foreground">{{ status }}: {{
|
||||
decisionDate.toLocaleString("en-US", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { getAllApplications, approveApplication, denyApplication, Status } from '@/api/application';
|
||||
import { getAllApplications, approveApplication, denyApplication, ApplicationStatus } from '@/api/application';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -87,7 +87,7 @@ onMounted(async () => {
|
||||
<TableCell :title="formatExact(app.submitted_at)">
|
||||
{{ formatAgo(app.submitted_at) }}
|
||||
</TableCell>
|
||||
<TableCell v-if="app.app_status === Status.Pending" class="inline-flex items-end gap-2">
|
||||
<TableCell v-if="app.app_status === ApplicationStatus.Pending" class="inline-flex items-end gap-2">
|
||||
<Button variant="success" @click.stop="() => { handleApprove(app.id) }">
|
||||
<CheckIcon></CheckIcon>
|
||||
</Button>
|
||||
@@ -97,9 +97,9 @@ onMounted(async () => {
|
||||
</TableCell>
|
||||
<TableCell class="text-right font-semibold" :class="[
|
||||
,
|
||||
app.app_status === Status.Pending && 'text-yellow-500',
|
||||
app.app_status === Status.Accepted && 'text-green-500',
|
||||
app.app_status === Status.Denied && 'text-destructive'
|
||||
app.app_status === ApplicationStatus.Pending && 'text-yellow-500',
|
||||
app.app_status === ApplicationStatus.Accepted && 'text-green-500',
|
||||
app.app_status === ApplicationStatus.Denied && 'text-destructive'
|
||||
]">{{ app.app_status }}</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
|
||||
@@ -42,7 +42,6 @@ router.beforeEach(async (to) => {
|
||||
|
||||
// Make sure user state is loaded before checking
|
||||
if (!user.loaded) {
|
||||
console.log('loaduser')
|
||||
await user.loadUser();
|
||||
}
|
||||
|
||||
@@ -55,12 +54,10 @@ router.beforeEach(async (to) => {
|
||||
}
|
||||
|
||||
|
||||
// Must be a member
|
||||
if (to.meta.memberOnly && user.state !== 'member') {
|
||||
return '/unauthorized'
|
||||
}
|
||||
|
||||
console.log(!user.hasRole("Dev"));
|
||||
// // Must be a member
|
||||
// if (to.meta.memberOnly && user.state !== 'member') {
|
||||
// return '/unauthorized'
|
||||
// }
|
||||
|
||||
// // Must have specific role
|
||||
// if (to.meta.roles && !user.hasRole('Dev') && !user.hasAnyRole(to.meta.roles)) {
|
||||
|
||||
@@ -16,7 +16,6 @@ export const useUserStore = defineStore('user', () => {
|
||||
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
console.log(data);
|
||||
user.value = data;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user