dev
This commit is contained in:
@@ -0,0 +1,420 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { enhance } from '$app/forms';
|
||||
import type { PageProps } from './$types';
|
||||
import { PERMISSIONS } from '$lib/consts';
|
||||
import { userPerms, employerPerms, adminPerms, telFormatter } from '$lib/shared.svelte';
|
||||
let permsAccordions: boolean[] = [false, false, false];
|
||||
|
||||
let passwordVisible = $state(false);
|
||||
|
||||
function showPassword() {
|
||||
const password = document.querySelector('input[name="password"]');
|
||||
if (password) {
|
||||
if (password.getAttribute('type') === 'password') {
|
||||
password.setAttribute('type', 'text');
|
||||
passwordVisible = true;
|
||||
} else {
|
||||
password.setAttribute('type', 'password');
|
||||
passwordVisible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
let acc = document.getElementsByClassName('accordion');
|
||||
for (let i = 0; i < acc.length; i++) {
|
||||
acc[i].addEventListener('click', function (this: HTMLElement, event: Event) {
|
||||
const target = event?.target as HTMLElement | null;
|
||||
if (target?.tagName === 'INPUT' && (target as HTMLInputElement).type === 'checkbox') {
|
||||
return; // Do nothing if it's the checkbox
|
||||
}
|
||||
|
||||
this.classList.toggle('active');
|
||||
permsAccordions[i] = !permsAccordions[i];
|
||||
|
||||
let panel = this.nextElementSibling as HTMLElement;
|
||||
if (panel.style.display === 'block') {
|
||||
panel.style.display = 'none';
|
||||
} else {
|
||||
panel.style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
let selectAllCheckbox = acc[i].querySelector('.select-all') as HTMLInputElement;
|
||||
selectAllCheckbox.addEventListener('change', function () {
|
||||
let checkboxes =
|
||||
this.parentElement!.parentElement!.parentElement!.nextElementSibling!.querySelectorAll(
|
||||
'.permCheckbox'
|
||||
) as NodeListOf<HTMLInputElement>;
|
||||
checkboxes.forEach((checkbox) => {
|
||||
checkbox.checked = selectAllCheckbox.checked;
|
||||
});
|
||||
});
|
||||
|
||||
let permCheckboxes = acc[i].nextElementSibling!.querySelectorAll(
|
||||
'.permCheckbox'
|
||||
) as NodeListOf<HTMLInputElement>;
|
||||
|
||||
permCheckboxes.forEach((checkbox) => {
|
||||
checkbox.addEventListener('change', function () {
|
||||
let allChecked = true;
|
||||
let someChecked = false;
|
||||
permCheckboxes.forEach((cb) => {
|
||||
if (cb.checked) {
|
||||
someChecked = true;
|
||||
} else {
|
||||
allChecked = false;
|
||||
}
|
||||
});
|
||||
selectAllCheckbox.checked = allChecked;
|
||||
selectAllCheckbox.indeterminate = !allChecked && someChecked;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const modal: HTMLElement = document.getElementById('deleteConfirmModal') as HTMLElement;
|
||||
window.onclick = function (event) {
|
||||
if (event.target == modal) {
|
||||
modal.style.display = 'none';
|
||||
}
|
||||
};
|
||||
document.getElementById('phone')?.addEventListener('input', function (this: HTMLInputElement) {
|
||||
this.value = telFormatter(this.value);
|
||||
});
|
||||
});
|
||||
|
||||
function openConfirm() {
|
||||
document.getElementById('deleteConfirmModal')!.style.display = 'block';
|
||||
}
|
||||
|
||||
function closeConfirm() {
|
||||
document.getElementById('deleteConfirmModal')!.style.display = 'none';
|
||||
}
|
||||
|
||||
let { data, form }: PageProps = $props();
|
||||
|
||||
let perms = data.user!.perms;
|
||||
</script>
|
||||
|
||||
<div class="content">
|
||||
<div class="elevated separator-borders m-4 rounded">
|
||||
<div class="bottom-border flex place-content-between">
|
||||
<div class="p-3 font-semibold">Update User</div>
|
||||
</div>
|
||||
<form method="POST" class="px-4" autocomplete="off" use:enhance>
|
||||
<div class="mt-4 text-sm font-semibold">
|
||||
Username <span class="text-red-500">*</span>
|
||||
<input
|
||||
type="text"
|
||||
name="username"
|
||||
id="username"
|
||||
value={data.user?.username}
|
||||
placeholder="Username"
|
||||
class="w-full rounded font-normal"
|
||||
/>
|
||||
</div>
|
||||
<div class="relative pt-4 text-sm font-semibold">
|
||||
Password
|
||||
<input
|
||||
type="password"
|
||||
name="password"
|
||||
id="password"
|
||||
placeholder="New password"
|
||||
class="w-full rounded font-normal"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onclick={showPassword}
|
||||
class="absolute right-2.5 -translate-y-1/2 transform pt-12"
|
||||
>
|
||||
<span class="material-symbols-outlined"
|
||||
>{passwordVisible ? 'visibility' : 'visibility_off'}</span
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-4 text-sm font-semibold">
|
||||
Email (optional)
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
value={data.user?.email}
|
||||
placeholder="Email"
|
||||
class="w-full rounded font-normal"
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-4 text-sm font-semibold">
|
||||
Phone (optional)
|
||||
<input
|
||||
type="tel"
|
||||
name="phone"
|
||||
id="phone"
|
||||
value={data.user?.phone}
|
||||
placeholder="Phone"
|
||||
class="w-full rounded font-normal"
|
||||
pattern="([0-9]\{3}) [0-9]\{3}-[0-9]\{3}"
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-4 text-sm font-semibold">
|
||||
Full name (optional)
|
||||
<input
|
||||
type="text"
|
||||
name="fullName"
|
||||
id="fullName"
|
||||
value={data.user?.fullName}
|
||||
placeholder="Full name"
|
||||
class="w-full rounded font-normal"
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-4 text-sm font-semibold">
|
||||
Company code (optional)
|
||||
<input
|
||||
type="text"
|
||||
name="companyCode"
|
||||
id="companyCode"
|
||||
placeholder="Company code"
|
||||
value={data.user?.companyCode}
|
||||
class="w-full rounded font-normal"
|
||||
/>
|
||||
</div>
|
||||
<p class="low-emphasis-text">
|
||||
This code can be used to associate an employer with their company. If left blank, they will
|
||||
not be able to create any postings.
|
||||
</p>
|
||||
<div class="bg-color separator-borders mb-2 mt-4 rounded">
|
||||
<button
|
||||
class="accordion flex w-full place-content-between rounded p-2 text-left"
|
||||
type="button"
|
||||
>
|
||||
<span class="flex place-items-center">
|
||||
<span class="ml-1 mr-3"
|
||||
><input
|
||||
type="checkbox"
|
||||
name="userPerms"
|
||||
id="userPerms"
|
||||
class="select-all"
|
||||
checked={(perms & userPerms) === userPerms}
|
||||
indeterminate={(perms & userPerms) !== userPerms && (perms & userPerms) !== 0}
|
||||
/></span
|
||||
>User Permissions
|
||||
</span>
|
||||
<span class="material-symbols-outlined"
|
||||
>{permsAccordions[0] ? 'arrow_drop_up' : 'arrow_drop_down'}</span
|
||||
>
|
||||
</button>
|
||||
<div class="panel hidden p-2">
|
||||
<div>
|
||||
<div class="mb-1">
|
||||
<label for="view" class="flex place-items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="view"
|
||||
id="view"
|
||||
class="permCheckbox mx-1"
|
||||
checked={(perms & PERMISSIONS.VIEW) !== 0}
|
||||
/>
|
||||
<span class="ml-2">View access</span></label
|
||||
>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<label for="apply" class="flex place-items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="apply"
|
||||
id="apply"
|
||||
class="permCheckbox mx-1"
|
||||
checked={(perms & PERMISSIONS.APPLY_FOR_JOBS) !== 0}
|
||||
/>
|
||||
<span class="ml-2">Apply for jobs</span></label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-color separator-borders my-2 rounded">
|
||||
<button
|
||||
class="accordion flex w-full place-content-between rounded p-2 text-left"
|
||||
type="button"
|
||||
>
|
||||
<span class="flex place-items-center">
|
||||
<span class="ml-1 mr-3"
|
||||
><input
|
||||
type="checkbox"
|
||||
name="companyPerms"
|
||||
id="companyPerms"
|
||||
class="select-all"
|
||||
checked={(perms & employerPerms) === employerPerms}
|
||||
indeterminate={(perms & employerPerms) !== employerPerms &&
|
||||
(perms & employerPerms) !== 0}
|
||||
/></span
|
||||
>Company Permissions
|
||||
</span>
|
||||
<span class="material-symbols-outlined"
|
||||
>{permsAccordions[1] ? 'arrow_drop_up' : 'arrow_drop_down'}</span
|
||||
>
|
||||
</button>
|
||||
<div class="panel hidden p-2">
|
||||
<div>
|
||||
<div class="mb-1">
|
||||
<label for="submitPostings" class="flex place-items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="submitPostings"
|
||||
id="submitPostings"
|
||||
checked={(perms & PERMISSIONS.SUBMIT_POSTINGS) !== 0}
|
||||
class="permCheckbox mx-1"
|
||||
/>
|
||||
<span class="ml-2">Submit postings</span></label
|
||||
>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<label for="manageEmployers" class="flex place-items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="manageEmployers"
|
||||
id="manageEmployers"
|
||||
checked={(perms & PERMISSIONS.MANAGE_EMPLOYERS) !== 0}
|
||||
class="permCheckbox mx-1"
|
||||
/>
|
||||
<span class="ml-2">Manage employers (within their company)</span></label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-color separator-borders mt-2 rounded">
|
||||
<button
|
||||
class="accordion flex w-full place-content-between rounded p-2 text-left"
|
||||
type="button"
|
||||
>
|
||||
<span class="flex place-items-center">
|
||||
<span class="ml-1 mr-3"
|
||||
><input
|
||||
type="checkbox"
|
||||
name="adminPerms"
|
||||
id="adminPerms"
|
||||
class="select-all"
|
||||
checked={(perms & adminPerms) === adminPerms}
|
||||
indeterminate={(perms & adminPerms) !== adminPerms && (perms & adminPerms) !== 0}
|
||||
/></span
|
||||
>Admin Permissions
|
||||
</span>
|
||||
<span class="material-symbols-outlined"
|
||||
>{permsAccordions[0] ? 'arrow_drop_up' : 'arrow_drop_down'}</span
|
||||
>
|
||||
</button>
|
||||
<div class="panel hidden p-2">
|
||||
<div>
|
||||
<div class="mb-1">
|
||||
<label for="manageTags" class="flex place-items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="manageTags"
|
||||
id="manageTags"
|
||||
checked={(perms & PERMISSIONS.MANAGE_TAGS) !== 0}
|
||||
class="permCheckbox mx-1"
|
||||
/>
|
||||
<span class="ml-2">Manage tags</span></label
|
||||
>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<label for="managePostings" class="flex place-items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="managePostings"
|
||||
id="managePostings"
|
||||
checked={(perms & PERMISSIONS.MANAGE_POSTINGS) !== 0}
|
||||
class="permCheckbox mx-1"
|
||||
/>
|
||||
<span class="ml-2">Manage postings</span></label
|
||||
>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<label for="manageUsers" class="flex place-items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="manageUsers"
|
||||
id="manageUsers"
|
||||
checked={(perms & PERMISSIONS.MANAGE_USERS) !== 0}
|
||||
class="permCheckbox mx-1"
|
||||
/>
|
||||
<span class="ml-2">Manage users</span></label
|
||||
>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<label for="manageCompanies" class="flex place-items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="manageCompanies"
|
||||
id="manageCompanies"
|
||||
checked={(perms & PERMISSIONS.MANAGE_COMPANIES) !== 0}
|
||||
class="permCheckbox mx-1"
|
||||
/>
|
||||
<span class="ml-2">Manage companies</span></label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label for="accountActive" class="flex place-items-center p-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="accountActive"
|
||||
id="accountActive"
|
||||
checked={data.user?.active}
|
||||
class="permCheckbox mx-1"
|
||||
/>
|
||||
<span class="ml-2">Account active</span></label
|
||||
>
|
||||
|
||||
{#if form?.errorMessage}
|
||||
<div class="mb-2 text-red-500">{form.errorMessage}</div>
|
||||
{/if}
|
||||
<div class="flex justify-between">
|
||||
<button
|
||||
class="dull-primary-bg-color mb-4 mt-2 rounded px-2 py-1"
|
||||
type="submit"
|
||||
formaction="?/submit">Update user</button
|
||||
>
|
||||
<button
|
||||
class="danger-bg-color mb-4 mt-2 rounded px-2 py-1"
|
||||
type="button"
|
||||
onclick={openConfirm}>Delete user</button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
<form id="deleteConfirmModal" class="modal" method="POST" use:enhance>
|
||||
<div class="modal-content">
|
||||
<div class="mb-2 inline-flex w-full justify-between">
|
||||
<h2 class="font-semibold">Are you sure?</h2>
|
||||
<button class="material-symbols-outlined" onclick={closeConfirm}>close</button>
|
||||
</div>
|
||||
<p>
|
||||
This will permanently delete user <span class="font-semibold">{data.user?.username}.</span
|
||||
>
|
||||
</p>
|
||||
<p>Please type "I understand" into the box below to confirm</p>
|
||||
<input
|
||||
type="text"
|
||||
name="confirm"
|
||||
id="confirm"
|
||||
placeholder="I understand"
|
||||
class="w-full rounded font-normal"
|
||||
pattern="I understand"
|
||||
required
|
||||
/>
|
||||
<div class="mt-4 flex justify-between">
|
||||
<button class="danger-bg-color rounded px-2 py-1" type="submit" formaction="?/delete"
|
||||
>Delete user</button
|
||||
>
|
||||
<button
|
||||
class="separator-borders bg-color rounded px-2 py-1"
|
||||
type="button"
|
||||
onclick={closeConfirm}>Cancel</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user