implemented some recruiter view features
This commit is contained in:
@@ -17,7 +17,7 @@ import ManageApplications from './pages/ManageApplications.vue';
|
|||||||
</div>
|
</div>
|
||||||
<Separator></Separator>
|
<Separator></Separator>
|
||||||
<Application></Application>
|
<Application></Application>
|
||||||
<!-- <ManageApplications></ManageApplications> -->
|
<ManageApplications></ManageApplications>
|
||||||
<!-- <AutoForm class="max-w-3xl mx-auto my-20"></AutoForm> -->
|
<!-- <AutoForm class="max-w-3xl mx-auto my-20"></AutoForm> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -63,3 +63,29 @@ export async function postChatMessage(val: any) {
|
|||||||
body: JSON.stringify(output),
|
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);
|
--accent-foreground: oklch(0.9243 0.1151 95.7459);
|
||||||
--destructive: oklch(0.6368 0.2078 25.3313);
|
--destructive: oklch(0.6368 0.2078 25.3313);
|
||||||
--destructive-foreground: oklch(1.0000 0 0);
|
--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);
|
--border: oklch(0.3715 0 0);
|
||||||
--input: oklch(0.3715 0 0);
|
--input: oklch(0.3715 0 0);
|
||||||
--ring: oklch(0.7686 0.1647 70.0804);
|
--ring: oklch(0.7686 0.1647 70.0804);
|
||||||
@@ -67,6 +69,8 @@
|
|||||||
--accent-foreground: oklch(0.9243 0.1151 95.7459);
|
--accent-foreground: oklch(0.9243 0.1151 95.7459);
|
||||||
--destructive: oklch(0.6368 0.2078 25.3313);
|
--destructive: oklch(0.6368 0.2078 25.3313);
|
||||||
--destructive-foreground: oklch(1.0000 0 0);
|
--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);
|
--border: oklch(0.3715 0 0);
|
||||||
--input: oklch(0.3715 0 0);
|
--input: oklch(0.3715 0 0);
|
||||||
--ring: oklch(0.7686 0.1647 70.0804);
|
--ring: oklch(0.7686 0.1647 70.0804);
|
||||||
@@ -115,6 +119,8 @@
|
|||||||
--color-accent-foreground: var(--accent-foreground);
|
--color-accent-foreground: var(--accent-foreground);
|
||||||
--color-destructive: var(--destructive);
|
--color-destructive: var(--destructive);
|
||||||
--color-destructive-foreground: var(--destructive-foreground);
|
--color-destructive-foreground: var(--destructive-foreground);
|
||||||
|
--color-success: var(--success);
|
||||||
|
--color-success-foreground: var(--success-foreground);
|
||||||
--color-border: var(--border);
|
--color-border: var(--border);
|
||||||
--color-input: var(--input);
|
--color-input: var(--input);
|
||||||
--color-ring: var(--ring);
|
--color-ring: var(--ring);
|
||||||
@@ -155,6 +161,7 @@
|
|||||||
* {
|
* {
|
||||||
@apply border-border outline-ring/50;
|
@apply border-border outline-ring/50;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ export const buttonVariants = cva(
|
|||||||
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
||||||
ghost:
|
ghost:
|
||||||
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
"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",
|
link: "text-primary underline-offset-4 hover:underline",
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { getAllApplications, approveApplication, denyApplication, Status } from '@/api/application';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@@ -8,32 +9,84 @@ import {
|
|||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from '@/components/ui/table'
|
} 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>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Table>
|
<Table>
|
||||||
<TableCaption>A list of your recent invoices.</TableCaption>
|
<!-- <TableCaption>A list of your recent invoices.</TableCaption> -->
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead class="w-[100px]">
|
<TableHead class="w-[100px]">User</TableHead>
|
||||||
Invoice
|
<TableHead>Date Submitted</TableHead>
|
||||||
</TableHead>
|
<TableHead class="text-right">Status</TableHead>
|
||||||
<TableHead>Status</TableHead>
|
|
||||||
<TableHead>Method</TableHead>
|
|
||||||
<TableHead class="text-right">
|
|
||||||
Amount
|
|
||||||
</TableHead>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
<TableRow>
|
<TableRow v-for="app in appList" :key="app.id">
|
||||||
<TableCell class="font-medium">
|
<TableCell class="font-medium">{{ app.member_name }}</TableCell>
|
||||||
INV001
|
<TableCell :title="formatExact(app.submitted_at)">
|
||||||
|
{{ formatAgo(app.submitted_at) }}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>Paid</TableCell>
|
<TableCell v-if="app.app_status != 'Pending'" class="text-right" :class="[
|
||||||
<TableCell>Credit Card</TableCell>
|
'font-semibold',
|
||||||
<TableCell class="text-right">
|
app.app_status === Status.Pending && 'text-yellow-500',
|
||||||
$250.00
|
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>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableBody>
|
</TableBody>
|
||||||
|
|||||||
Reference in New Issue
Block a user