dev
All checks were successful
ci / docker_image (push) Successful in 1m37s
ci / deploy (push) Successful in 16s

This commit is contained in:
Drake Marino 2025-01-31 18:51:20 -06:00
parent 5eca1635f5
commit 2acc65823b
15 changed files with 162 additions and 113 deletions

View File

@ -306,7 +306,7 @@ export async function deleteCompany(id: number): Promise<void> {
export async function getCompany(id: number): Promise<Company> {
const [company] = await sql`
SELECT id, name, description, website, created_at AS "createdAt"
SELECT id, name, description, website, created_at AS "createdAt", company_code AS "companyCode"
FROM companies
WHERE id = ${id};
`;
@ -750,3 +750,12 @@ export async function getApplications(postingId: number): Promise<Application[]>
return <Application[]>(<unknown>data);
}
export async function setUserCompanyId(userId: number, companyId: number): Promise<void> {
await sql`
UPDATE users
SET company_id = ${companyId},
company_code = (SELECT company_code FROM companies WHERE id = ${companyId})
WHERE id = ${userId};
`;
}

View File

@ -119,7 +119,7 @@
{#if data.user.company?.id}
<div class="font-semibold">
Employer company:
<div class="top-border mt-2 p-3">
<div class="top-border mt-2 p-3 align-top">
<img
id="logo"
class="mb-2 inline-block rounded"
@ -129,7 +129,7 @@
height="32"
width="32"
/>
<div class="inline-block">
<div class="inline-block pl-2 align-top">
<div>{data.user.company.name}</div>
<div class="max-char-length font-normal">{data.user.company.description}</div>
</div>

View File

@ -147,7 +147,7 @@
id="phone"
placeholder="Phone"
class="w-full rounded font-normal"
pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}"
pattern="([0-9]\{3}) [0-9]\{3}-[0-9]\{3}"
/>
</div>
<div class="mt-4 text-sm font-semibold">

View File

@ -1,6 +1,8 @@
<script lang="ts">
import type { PageProps } from './$types';
import type { Company, User } from '$lib/types';
import type { Company } from '$lib/types';
import { userState } from '$lib/shared.svelte';
import { PERMISSIONS } from '$lib/consts';
function logoFallback(e: Event, company: Company) {
(e.target as HTMLImageElement).src =
@ -13,7 +15,15 @@
<div class="base-container-small">
<div class="content">
<div class="elevated separator-borders mb-4 mt-4 rounded">
<div class="p-3 font-semibold">Companies</div>
<div class="flex justify-between">
<div class="inline-block p-3 font-semibold">Companies</div>
{#if (userState.perms & PERMISSIONS.MANAGE_COMPANIES) > 0 || (userState.perms & PERMISSIONS.SUBMIT_POSTINGS) > 0}
<a
class="dull-primary-bg-color m-2 inline-block rounded-md px-2.5 py-1"
href="/companies/create">Create new company</a
>
{/if}
</div>
{#each data.companies as company}
<a class="top-border hover-bg-color inline-block w-full p-3" href="/companies/{company.id}">
<img

View File

@ -27,9 +27,8 @@ export const actions: Actions = {
const requestPerms = getUserPerms(cookies);
if (
!(
requestPerms >= 0 &&
((requestPerms & PERMISSIONS.MANAGE_COMPANIES) > 0 ||
((requestPerms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && getUserCompanyId(cookies) === id))
(requestPerms >= 0 && (requestPerms & PERMISSIONS.MANAGE_COMPANIES) > 0) ||
(requestPerms & PERMISSIONS.SUBMIT_POSTINGS) > 0
)
) {
return fail(403, { errorMessage: 'You cannot preform this action!' });

View File

@ -10,11 +10,30 @@
document.getElementById('deleteConfirmModal')!.style.display = 'none';
}
function logoFallback(e: Event) {
(e.target as HTMLImageElement).src =
`https://ui-avatars.com/api/?background=random&format=svg&name=${encodeURIComponent(data.company.name!)}`;
}
let { data, form }: PageProps = $props();
</script>
<div class="base-container">
<div class="content">
<div class="m-4">
<img
class="mb-2 inline-block rounded-lg"
src="/uploads/logos/{data.company.id}.svg?timestamp=${Date.now()}"
alt="User avatar"
onerror={logoFallback}
height="80"
width="80"
/>
<div class="inline-block pl-4 align-top">
<h1 class="font-bold">{data.company.name}</h1>
<h2>Company code: <span class="font-semibold">{data.company.companyCode}</span></h2>
</div>
</div>
<div class="elevated separator-borders m-4 rounded">
<div class="bottom-border flex place-content-between">
<div class="p-3 font-semibold">Edit Company {data.company.name}</div>

View File

@ -14,9 +14,8 @@ export const actions: Actions = {
const requestPerms = getUserPerms(cookies);
if (
!(
requestPerms >= 0 &&
((requestPerms & PERMISSIONS.MANAGE_COMPANIES) > 0 ||
((requestPerms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && getUserCompanyId(cookies)))
(requestPerms >= 0 && (requestPerms & PERMISSIONS.MANAGE_COMPANIES) > 0) ||
(requestPerms & PERMISSIONS.SUBMIT_POSTINGS) > 0
)
) {
return fail(403, { errorMessage: 'You cannot preform this action!' });

View File

@ -14,10 +14,10 @@
access to create job postings.
</p>
<p>
If you are your company admin, first create your account (without inputting a code). Then, go
to the company page, and use the button in the top right to create a new company. Once created
and approved by a CareerConnect admin, you will be able to see the company code, which you can
then give to your employees.
If you are your company admin, first create your account (without inputting a code). Reach out
to a CareerConnect admin to elevate your account privaleges. Then, go to the company page, and
use the button in the top right to create a new company. Once created, you will be able to see
the company code, which you can then give to your employees.
</p>
</div>
</div>

View File

@ -36,7 +36,16 @@
</script>
<div class="base-container">
<div class="content flex">
<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
@ -64,7 +73,7 @@
</div>
{#if details !== undefined}
<div
class="elevated separator-borders top-with-navbar sticky ml-4 mt-4 inline-block h-min w-2/3 rounded p-4"
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">
@ -109,7 +118,8 @@
{#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
class="block w-max"
>Address: <span class="hover-hyperlink">{details.address}</span></a
>
{/if}
{#if details.wage}
@ -138,3 +148,4 @@
{/if}
</div>
</div>
</div>

View File

@ -36,7 +36,7 @@
<h2>Company: {data.posting.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))}
{#if userState.perms >= 0 && ((userState.perms & PERMISSIONS.MANAGE_POSTINGS) > 0 || ((userState.perms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && userState.companyId === data.posting.company.id))}
<a
class="dull-primary-bg-color inline-block h-min rounded-md px-2.5 py-1 align-top"
href="/postings/{data.posting.id}/manage">Manage posting</a

View File

@ -14,7 +14,7 @@ export const load: PageServerLoad = async ({ params, cookies }) => {
if (
perms >= 0 &&
((perms & PERMISSIONS.MANAGE_POSTINGS) > 0 ||
((perms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && getUserCompanyId(cookies) === id))
((perms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && getUserCompanyId(cookies)))
) {
return {
applications: await getApplications(id)

View File

@ -78,7 +78,7 @@
<p>Email: {application.user.email}</p>
{/if}
{#if application.user?.phone}
<p>Phone: {application.user.email}</p>
<p>Phone: {application.user.phone}</p>
{/if}
{#if application.createdAt}
<p>

View File

@ -9,10 +9,11 @@ export const load: PageServerLoad = async ({ cookies, params }) => {
const id = parseInt(params.posting);
const perms = getUserPerms(cookies);
// TODO check if user is allowed to edit this posting
if (
perms >= 0 &&
((perms & PERMISSIONS.MANAGE_POSTINGS) > 0 ||
((perms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && getUserCompanyId(cookies) === id))
((perms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && getUserCompanyId(cookies)))
) {
return {
posting: await getPosting(id)

View File

@ -47,7 +47,8 @@ export const actions: Actions = {
active: true,
email: email,
phone: phone,
fullName: fullName
fullName: fullName,
companyCode: companyCode
};
if (password === confirmPassword) {
try {

View File

@ -83,7 +83,7 @@
id="phone"
placeholder="Phone"
class="w-full rounded font-normal"
pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}"
pattern="([0-9]\{3}) [0-9]\{3}-[0-9]\{3}"
/>
</div>
<div class="relative mt-4 text-sm font-semibold">