152 lines
5.0 KiB
Svelte
152 lines
5.0 KiB
Svelte
<script lang="ts">
|
|
import type { PageProps } from './$types';
|
|
import type { Posting } from '$lib/types';
|
|
import { onMount } from 'svelte';
|
|
import { employmentTypeDisplayName, userState } from '$lib/shared.svelte';
|
|
import { PERMISSIONS } from '$lib/consts';
|
|
let details: Posting | undefined = $state<Posting>();
|
|
|
|
const dateFormatOptions: Intl.DateTimeFormatOptions = {
|
|
year: 'numeric',
|
|
month: 'short',
|
|
day: 'numeric'
|
|
};
|
|
|
|
function logoFallback(e: Event, posting: Posting | undefined) {
|
|
(e.target as HTMLImageElement).src =
|
|
`https://ui-avatars.com/api/?background=random&format=svg&name=${encodeURIComponent(posting?.company.name || 'COMPANY')}`;
|
|
}
|
|
|
|
async function fetchDetails(id: number) {
|
|
const response = await fetch(`/api/posting?id=${id}`);
|
|
details = await response.json();
|
|
if (details?.createdAt) {
|
|
details.createdAt = new Date(details.createdAt);
|
|
}
|
|
if (details?.updatedAt) {
|
|
details.updatedAt = new Date(details.updatedAt);
|
|
}
|
|
}
|
|
|
|
let { data }: PageProps = $props();
|
|
|
|
onMount(async () => {
|
|
await fetchDetails(data.postings[0].id);
|
|
});
|
|
</script>
|
|
|
|
<div class="base-container">
|
|
<div class="content">
|
|
<div class="bottom-border mb-4 flex justify-between pb-2">
|
|
<h1 class="inline-block p-2">Postings</h1>
|
|
{#if userState.companyId && (userState.perms & PERMISSIONS.SUBMIT_POSTINGS) > 0}
|
|
<a class="dull-primary-bg-color m-2 h-min rounded-md px-2.5 py-1" href="/postings/create"
|
|
>Create new posting</a
|
|
>
|
|
{/if}
|
|
</div>
|
|
<div class="flex">
|
|
<div class="right-border inline-block w-1/3">
|
|
{#each data.postings as posting}
|
|
<button
|
|
class="bottom-border block w-full p-4 text-left {details?.id === posting.id
|
|
? 'accent-bg-color'
|
|
: ''}"
|
|
onclick={() => {
|
|
fetchDetails(posting.id);
|
|
}}
|
|
>
|
|
<img
|
|
class="inline-block rounded"
|
|
src="/uploads/logos/{posting.companyId}.svg"
|
|
alt="Company Logo"
|
|
height="48"
|
|
width="48"
|
|
onerror={(e) => logoFallback(e, posting)}
|
|
/>
|
|
<div class="inline-block pl-2 align-top">
|
|
<h2 class="font-semibold">{posting.title}</h2>
|
|
<h3>{posting.company.name}</h3>
|
|
</div>
|
|
</button>
|
|
{/each}
|
|
</div>
|
|
{#if details !== undefined}
|
|
<div
|
|
class="elevated separator-borders top-with-navbar sticky ml-4 inline-block h-min w-2/3 rounded p-4"
|
|
>
|
|
<div class="bottom-border flex justify-between pb-2">
|
|
<div class="inline-block">
|
|
<img
|
|
class="inline-block rounded"
|
|
src="/uploads/logos/{details.companyId || 'default'}.svg"
|
|
alt="Company Logo"
|
|
height="64"
|
|
width="64"
|
|
onerror={(e) => logoFallback(e, details)}
|
|
/>
|
|
<div class="inline-block pl-2 align-top">
|
|
<h1>{details.title}</h1>
|
|
<h2>Company: {details.company.name}</h2>
|
|
</div>
|
|
</div>
|
|
{#if userState.perms >= 0 && ((userState.perms & PERMISSIONS.MANAGE_POSTINGS) > 0 || ((userState.perms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && userState.companyId === details.company.id))}
|
|
<a
|
|
class="dull-primary-bg-color inline-block h-min rounded-md px-2.5 py-1 align-top"
|
|
href="/postings/{details.id}/manage">Manage posting</a
|
|
>
|
|
{:else if (userState.perms & PERMISSIONS.APPLY_FOR_JOBS) > 0}
|
|
<a
|
|
class="dull-primary-bg-color inline-block h-min rounded-md px-2.5 py-1 align-top"
|
|
href="/postings/{details.id}/apply">Apply</a
|
|
>
|
|
{/if}
|
|
</div>
|
|
<div class="scrollbar-on-elevated details-height overflow-y-scroll">
|
|
<h2 class="pt-2 font-semibold">Contact</h2>
|
|
<p>{details.employer?.fullName} ({details.employer?.username})</p>
|
|
<a class="hover-hyperlink" href="mailto:{details.employer?.email}"
|
|
>{details.employer?.email}</a
|
|
>
|
|
<a class="hover-hyperlink" href="tel:{details.employer?.phone}"
|
|
>{details.employer?.phone}</a
|
|
>
|
|
<h2 class="pt-2 font-semibold">Details</h2>
|
|
{#if details.employmentType}
|
|
<p>{employmentTypeDisplayName(details.employmentType)}</p>
|
|
{/if}
|
|
{#if details.address}
|
|
<a
|
|
href="https://www.google.com/maps/search/?api=1&query={details.address}"
|
|
class="block w-max"
|
|
>Address: <span class="hover-hyperlink">{details.address}</span></a
|
|
>
|
|
{/if}
|
|
{#if details.wage}
|
|
<p>Wage: {details.wage}</p>
|
|
{/if}
|
|
{#if details.createdAt}
|
|
<p>Posted: {details.createdAt.toLocaleDateString('en-US', dateFormatOptions)}</p>
|
|
{/if}
|
|
{#if details.link}
|
|
<a href={details.link} class="block w-max"
|
|
>More information: <span class="hyperlink-color hyperlink-underline"
|
|
>{details.link}</span
|
|
></a
|
|
>
|
|
{/if}
|
|
{#if details.flyerLink}
|
|
<a href={details.flyerLink} class="block w-max"
|
|
>Flyer: <span class="hyperlink-color hyperlink-underline">{details.flyerLink}</span
|
|
></a
|
|
>
|
|
{/if}
|
|
<h2 class="pt-2 font-semibold">Job Description</h2>
|
|
<p class="whitespace-pre-wrap">{details.description}</p>
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
</div>
|