implemented some recruiter view features
This commit is contained in:
@@ -17,7 +17,7 @@ import ManageApplications from './pages/ManageApplications.vue';
|
||||
</div>
|
||||
<Separator></Separator>
|
||||
<Application></Application>
|
||||
<!-- <ManageApplications></ManageApplications> -->
|
||||
<ManageApplications></ManageApplications>
|
||||
<!-- <AutoForm class="max-w-3xl mx-auto my-20"></AutoForm> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -63,3 +63,29 @@ export async function postChatMessage(val: any) {
|
||||
body: JSON.stringify(output),
|
||||
})
|
||||
}
|
||||
|
||||
export async function getAllApplications() {
|
||||
const res = await fetch(`http://${addr}/application/all`)
|
||||
|
||||
if (res.ok) {
|
||||
return await res.json();
|
||||
} else {
|
||||
console.error("Something went wrong approving the application")
|
||||
}
|
||||
}
|
||||
|
||||
export async function approveApplication(id: Number) {
|
||||
const res = await fetch(`http://${addr}/application/approve/${id}`, { method: 'POST' })
|
||||
|
||||
if (!res.ok) {
|
||||
console.error("Something went wrong approving the application")
|
||||
}
|
||||
}
|
||||
|
||||
export async function denyApplication(id: Number) {
|
||||
const res = await fetch(`http://${addr}/application/deny/${id}`, { method: 'POST' })
|
||||
|
||||
if (!res.ok) {
|
||||
console.error("Something went wrong approving the application")
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,8 @@
|
||||
--accent-foreground: oklch(0.9243 0.1151 95.7459);
|
||||
--destructive: oklch(0.6368 0.2078 25.3313);
|
||||
--destructive-foreground: oklch(1.0000 0 0);
|
||||
--success: oklch(66.104% 0.16937 144.153);
|
||||
--success-foreground: oklch(1.0000 0 0);
|
||||
--border: oklch(0.3715 0 0);
|
||||
--input: oklch(0.3715 0 0);
|
||||
--ring: oklch(0.7686 0.1647 70.0804);
|
||||
@@ -67,6 +69,8 @@
|
||||
--accent-foreground: oklch(0.9243 0.1151 95.7459);
|
||||
--destructive: oklch(0.6368 0.2078 25.3313);
|
||||
--destructive-foreground: oklch(1.0000 0 0);
|
||||
--success: oklch(66.104% 0.16937 144.153);
|
||||
--success-foreground: oklch(1.0000 0 0);
|
||||
--border: oklch(0.3715 0 0);
|
||||
--input: oklch(0.3715 0 0);
|
||||
--ring: oklch(0.7686 0.1647 70.0804);
|
||||
@@ -115,6 +119,8 @@
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-destructive-foreground: var(--destructive-foreground);
|
||||
--color-success: var(--success);
|
||||
--color-success-foreground: var(--success-foreground);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
@@ -155,6 +161,7 @@
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ export const buttonVariants = cva(
|
||||
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
||||
ghost:
|
||||
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
||||
success:
|
||||
"bg-success text-success-foreground shadow-xs hover:bg-success/90",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup>
|
||||
import { getAllApplications, approveApplication, denyApplication, Status } from '@/api/application';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -8,32 +9,84 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table'
|
||||
import Button from '@/components/ui/button/Button.vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
const appList = ref([]);
|
||||
const now = Date.now();
|
||||
// relative time formatter (uses user locale)
|
||||
const rtf = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' })
|
||||
// exact date/time for tooltip
|
||||
const exactFmt = new Intl.DateTimeFormat(undefined, {
|
||||
dateStyle: 'medium', timeStyle: 'short', timeZone: 'America/Toronto'
|
||||
})
|
||||
|
||||
function formatAgo(iso) {
|
||||
const d = new Date(iso)
|
||||
if (isNaN(d)) return ''
|
||||
let diff = (d.getTime() - now) / 1000 // seconds relative to page load
|
||||
const divisions = [
|
||||
{ amount: 60, name: 'second' },
|
||||
{ amount: 60, name: 'minute' },
|
||||
{ amount: 24, name: 'hour' },
|
||||
{ amount: 7, name: 'day' },
|
||||
{ amount: 4.34524, name: 'week' }, // avg weeks per month
|
||||
{ amount: 12, name: 'month' },
|
||||
{ amount: Infinity, name: 'year' },
|
||||
]
|
||||
for (const div of divisions) {
|
||||
if (Math.abs(diff) < div.amount) {
|
||||
return rtf.format(Math.round(diff), div.name)
|
||||
}
|
||||
diff /= div.amount
|
||||
}
|
||||
}
|
||||
|
||||
function formatExact(iso) {
|
||||
const d = new Date(iso)
|
||||
return isNaN(d) ? '' : exactFmt.format(d)
|
||||
}
|
||||
|
||||
async function handleApprove(id) {
|
||||
await approveApplication(id);
|
||||
appList.value = await getAllApplications();
|
||||
}
|
||||
|
||||
async function handleDeny(id) {
|
||||
await denyApplication(id);
|
||||
appList.value = await getAllApplications();
|
||||
}
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
appList.value = await getAllApplications();
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<Table>
|
||||
<TableCaption>A list of your recent invoices.</TableCaption>
|
||||
<!-- <TableCaption>A list of your recent invoices.</TableCaption> -->
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead class="w-[100px]">
|
||||
Invoice
|
||||
</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Method</TableHead>
|
||||
<TableHead class="text-right">
|
||||
Amount
|
||||
</TableHead>
|
||||
<TableHead class="w-[100px]">User</TableHead>
|
||||
<TableHead>Date Submitted</TableHead>
|
||||
<TableHead class="text-right">Status</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell class="font-medium">
|
||||
INV001
|
||||
<TableRow v-for="app in appList" :key="app.id">
|
||||
<TableCell class="font-medium">{{ app.member_name }}</TableCell>
|
||||
<TableCell :title="formatExact(app.submitted_at)">
|
||||
{{ formatAgo(app.submitted_at) }}
|
||||
</TableCell>
|
||||
<TableCell>Paid</TableCell>
|
||||
<TableCell>Credit Card</TableCell>
|
||||
<TableCell class="text-right">
|
||||
$250.00
|
||||
<TableCell v-if="app.app_status != 'Pending'" class="text-right" :class="[
|
||||
'font-semibold',
|
||||
app.app_status === Status.Pending && 'text-yellow-500',
|
||||
app.app_status === Status.Approved && 'text-success',
|
||||
app.app_status === Status.Denied && 'text-destructive'
|
||||
]">{{ app.app_status }}</TableCell>
|
||||
<TableCell v-else class="inline-flex items-end gap-2">
|
||||
<Button variant="success" :onClick="() => { handleApprove(app.id) }">Approve</Button>
|
||||
<Button variant="destructive" :onClick="() => { handleDeny(app.id) }">Deny</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
|
||||
Reference in New Issue
Block a user