add: carEditForm
This commit is contained in:
252
frontend/src/lib/components/CarEditForm.svelte
Normal file
252
frontend/src/lib/components/CarEditForm.svelte
Normal file
@@ -0,0 +1,252 @@
|
||||
<script>
|
||||
import InputField from '$lib/components/InputField.svelte';
|
||||
import SmallLoader from '$lib/components/SmallLoader.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { applyAction, enhance } from '$app/forms';
|
||||
import { hasPrivilige, receive, send } from '$lib/utils/helpers';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { defaultCar } from '$lib/utils/defaults';
|
||||
import { PERMISSIONS } from '$lib/utils/constants';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
/** @type {import('../../routes/auth/about/[id]/$types').ActionData} */
|
||||
export let form;
|
||||
|
||||
/** @type {App.Locals['user'] } */
|
||||
export let editor;
|
||||
|
||||
/** @type {App.Types['car'] | null} */
|
||||
export let car;
|
||||
|
||||
console.log('Opening car modal with:', car);
|
||||
$: car = car || { ...defaultCar() };
|
||||
$: isLoading = car === undefined || editor === undefined;
|
||||
let isUpdating = false;
|
||||
let readonlyUser = !hasPrivilige(editor, PERMISSIONS.Update);
|
||||
|
||||
const TABS = ['car.car', 'insurance', 'car.damages'];
|
||||
let activeTab = TABS[0];
|
||||
|
||||
/** @type {import('../../routes/auth/about/[id]/$types').SubmitFunction} */
|
||||
const handleUpdate = async () => {
|
||||
isUpdating = true;
|
||||
return async ({ result }) => {
|
||||
isUpdating = false;
|
||||
if (result.type === 'success' || result.type === 'redirect') {
|
||||
dispatch('close');
|
||||
} else {
|
||||
document.querySelector('.modal .container')?.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
await applyAction(result);
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if isLoading}
|
||||
<SmallLoader width={30} message={$t('loading.car_data')} />
|
||||
{:else if editor && car}
|
||||
<form class="content" action="?/updateCar" method="POST" use:enhance={handleUpdate}>
|
||||
<input name="susbscription[id]" type="hidden" bind:value={car.id} />
|
||||
<h1 class="step-title" style="text-align: center;">
|
||||
{car.id ? $t('car.edit') : $t('car.create')}
|
||||
</h1>
|
||||
{#if form?.errors}
|
||||
{#each form?.errors as error (error.id)}
|
||||
<h4
|
||||
class="step-subtitle warning"
|
||||
in:receive|global={{ key: error.id }}
|
||||
out:send|global={{ key: error.id }}
|
||||
>
|
||||
{$t(error.field) + ': ' + $t(error.key)}
|
||||
</h4>
|
||||
{/each}
|
||||
{/if}
|
||||
<div class="button-container">
|
||||
{#each TABS as tab}
|
||||
<button
|
||||
type="button"
|
||||
class="button-dark"
|
||||
class:active={activeTab === tab}
|
||||
on:click={() => (activeTab = tab)}
|
||||
>
|
||||
{$t(tab)}
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="tab-content" style="display: {activeTab === 'car.car' ? 'block' : 'none'}">
|
||||
<InputField
|
||||
name="car[name]"
|
||||
label={$t('name')}
|
||||
bind:value={car.name}
|
||||
placeholder={$t('placeholder.car_name')}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[brand]"
|
||||
label={$t('car.brand')}
|
||||
bind:value={car.brand}
|
||||
placeholder={$t('placeholder.car_brand')}
|
||||
required={true}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[model]"
|
||||
label={$t('car.model')}
|
||||
bind:value={car.model}
|
||||
placeholder={$t('placeholder.car_model')}
|
||||
required={true}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[color]"
|
||||
label={$t('color')}
|
||||
bind:value={car.color}
|
||||
placeholder={$t('placeholder.car_color')}
|
||||
required={true}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[licence_plate]"
|
||||
label={$t('car.licence_plate')}
|
||||
bind:value={car.licence_plate}
|
||||
placeholder={$t('placeholder.car_licence_plate')}
|
||||
required={true}
|
||||
toUpperCase={true}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[price]"
|
||||
type="number"
|
||||
label={$t('price')}
|
||||
bind:value={car.price}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[rate]"
|
||||
type="number"
|
||||
label={$t('car.leasing_rate')}
|
||||
bind:value={car.rate}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[start_date]"
|
||||
type="date"
|
||||
label={$t('car.start_date')}
|
||||
bind:value={car.start_date}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[end_date]"
|
||||
type="date"
|
||||
label={$t('car.end_date')}
|
||||
bind:value={car.end_date}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[notes]"
|
||||
type="textarea"
|
||||
label={$t('notes')}
|
||||
bind:value={car.notes}
|
||||
placeholder={$t('placeholder.notes', {
|
||||
values: { name: car.name || car.brand + ' ' + car.model }
|
||||
})}
|
||||
rows={10}
|
||||
/>
|
||||
</div>
|
||||
<div class="tab-content" style="display: {activeTab === 'insurance' ? 'block' : 'none'}">
|
||||
{#each car.insurances as insurance}
|
||||
<InputField
|
||||
name="car[insurance][company]"
|
||||
label={$t('company')}
|
||||
bind:value={insurance.company}
|
||||
placeholder={$t('placeholder.company')}
|
||||
required={true}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[insurance][reference]"
|
||||
label={$t('insurance.reference')}
|
||||
bind:value={insurance.reference}
|
||||
placeholder={$t('placeholder.insurance_reference')}
|
||||
required={true}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[insurance][start_date]"
|
||||
type="date"
|
||||
label={$t('start')}
|
||||
bind:value={insurance.start_date}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[insurance][end_date]"
|
||||
type="date"
|
||||
label={$t('end')}
|
||||
bind:value={insurance.end_date}
|
||||
readonly={readonlyUser}
|
||||
/>
|
||||
<InputField
|
||||
name="car[insurance][notes]"
|
||||
type="textarea"
|
||||
label={$t('notes')}
|
||||
bind:value={insurance.notes}
|
||||
placeholder={$t('placeholder.notes', {
|
||||
values: { name: insurance.company || '' }
|
||||
})}
|
||||
rows={10}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="button-container">
|
||||
{#if isUpdating}
|
||||
<SmallLoader width={30} message={$t('loading.updating')} />
|
||||
{:else}
|
||||
<button type="button" class="button-dark" on:click={() => dispatch('cancel')}>
|
||||
{$t('cancel')}</button
|
||||
>
|
||||
<button type="submit" class="button-dark">{$t('confirm')}</button>
|
||||
{/if}
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.tab-content {
|
||||
padding: 1rem;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background-color: var(--surface0);
|
||||
border: 1px solid var(--surface1);
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-top: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button-container button {
|
||||
flex: 1 1 0;
|
||||
min-width: 120px;
|
||||
max-width: calc(50% - 5px);
|
||||
background-color: var(--surface1);
|
||||
color: var(--text);
|
||||
border: 1px solid var(--overlay0);
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.button-container button:hover {
|
||||
background-color: var(--surface2);
|
||||
border-color: var(--lavender);
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.button-container button {
|
||||
flex-basis: 100%;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user