mirror of
https://github.com/danbulant/Portfolio
synced 2026-05-24 12:35:31 +00:00
feat: edit personal details
This commit is contained in:
parent
a59b06d18c
commit
23c577fd52
4 changed files with 209 additions and 104 deletions
|
|
@ -7,7 +7,8 @@
|
|||
import StatusNotificationBig from './StatusNotificationBig.svelte';
|
||||
import InfoButton from './InfoButton.svelte';
|
||||
import { candidateData } from '$lib/stores/candidate';
|
||||
import tippy from 'tippy.js';
|
||||
import tippy, {sticky} from 'tippy.js';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
export let title: string;
|
||||
export let status: Status;
|
||||
|
|
@ -58,6 +59,10 @@
|
|||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
const editDetails = async () => {
|
||||
goto('/register?edit=true')
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="card flex flex-col">
|
||||
|
|
@ -86,52 +91,65 @@
|
|||
</div>
|
||||
</div>
|
||||
{#if showDetails}
|
||||
<div class="overflow-scroll">
|
||||
<div
|
||||
<div class="overflow-scroll flex justify-between">
|
||||
<div>
|
||||
<div
|
||||
use:tippy={{
|
||||
content: '<span>Vámi vyplněné osobní údaje</span>',
|
||||
allowHTML: true,
|
||||
placement: 'top',
|
||||
showOnCreate: false,
|
||||
delay: 0
|
||||
}}
|
||||
class="mt-4 flex flex-col justify-between leading-10"
|
||||
>
|
||||
<span>Adresa: <span class="font-bold">{$candidateData.candidate.address}</span></span>
|
||||
<span
|
||||
>Datum narození: <span class="font-bold">{$candidateData.candidate.birthdate}</span
|
||||
></span
|
||||
>
|
||||
<span
|
||||
>Místo narození: <span class="font-bold">{$candidateData.candidate.birthplace}</span
|
||||
></span
|
||||
>
|
||||
<span
|
||||
>Rodné číslo: <span class="font-bold">{$candidateData.candidate.personalIdNumber}</span
|
||||
></span
|
||||
>
|
||||
<span>Telefon: <span class="font-bold">{$candidateData.candidate.telephone}</span></span>
|
||||
</div>
|
||||
<div
|
||||
use:tippy={{
|
||||
content: '<span>Vámi vyplněné osobní údaje</span>',
|
||||
allowHTML: true,
|
||||
placement: 'top',
|
||||
showOnCreate: false,
|
||||
delay: 0
|
||||
}}
|
||||
class="mt-4 flex flex-col leading-10"
|
||||
>
|
||||
{#each $candidateData.parents as parent}
|
||||
<div class="flex flex-col">
|
||||
<span class="text-sspsBlue text-xl font-bold"
|
||||
>{parent.name + ' ' + parent.surname}</span
|
||||
>
|
||||
<span>Email: <span class="font-bold">{parent.email}</span></span>
|
||||
<span>Telefon: <span class="font-bold">{parent.telephone}</span></span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
use:tippy={{
|
||||
content: '<span>Vámi vyplněné osobní údaje</span>',
|
||||
allowHTML: true,
|
||||
content: 'Upravit osobní údaje',
|
||||
placement: 'top',
|
||||
showOnCreate: false,
|
||||
delay: 0
|
||||
sticky: true,
|
||||
plugins: [sticky]
|
||||
}}
|
||||
class="mt-4 flex flex-col justify-between leading-10"
|
||||
>
|
||||
<span>Adresa: <span class="font-bold">{$candidateData.candidate.address}</span></span>
|
||||
<span
|
||||
>Datum narození: <span class="font-bold">{$candidateData.candidate.birthdate}</span
|
||||
></span
|
||||
>
|
||||
<span
|
||||
>Místo narození: <span class="font-bold">{$candidateData.candidate.birthplace}</span
|
||||
></span
|
||||
>
|
||||
<span
|
||||
>Rodné číslo: <span class="font-bold">{$candidateData.candidate.personalIdNumber}</span
|
||||
></span
|
||||
>
|
||||
<span>Telefon: <span class="font-bold">{$candidateData.candidate.telephone}</span></span>
|
||||
</div>
|
||||
<div
|
||||
use:tippy={{
|
||||
content: '<span>Vámi vyplněné osobní údaje</span>',
|
||||
allowHTML: true,
|
||||
placement: 'top',
|
||||
showOnCreate: false,
|
||||
delay: 0
|
||||
}}
|
||||
class="mt-4 flex flex-col leading-10"
|
||||
>
|
||||
{#each $candidateData.parents as parent}
|
||||
<div class="flex flex-col">
|
||||
<span class="text-sspsBlue text-xl font-bold"
|
||||
>{parent.name + ' ' + parent.surname}</span
|
||||
>
|
||||
<span>Email: <span class="font-bold">{parent.email}</span></span>
|
||||
<span>Telefon: <span class="font-bold">{parent.telephone}</span></span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
on:click={(_) => editDetails()} on:keydown={(_) => editDetails()} class="mt-4 hover:cursor-pointer">
|
||||
<svg class="w-10 h-10 stroke-sspsBlue" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path></svg>
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,23 +2,23 @@ import { writable } from 'svelte/store';
|
|||
|
||||
export interface CandidateData {
|
||||
candidate: {
|
||||
name?: string;
|
||||
surname?: string;
|
||||
birthplace?: string;
|
||||
birthdate?: string;
|
||||
address?: string;
|
||||
telephone?: string;
|
||||
citizenship?: string;
|
||||
email?: string;
|
||||
sex?: string;
|
||||
study?: string;
|
||||
personalIdNumber?: string;
|
||||
name: string;
|
||||
surname: string;
|
||||
birthplace: string;
|
||||
birthdate: string;
|
||||
address: string;
|
||||
telephone: string;
|
||||
citizenship: string;
|
||||
email: string;
|
||||
sex: string;
|
||||
study: string;
|
||||
personalIdNumber: string;
|
||||
};
|
||||
parents: Array<{
|
||||
name?: string;
|
||||
surname?: string;
|
||||
telephone?: string;
|
||||
email?: string;
|
||||
name: string;
|
||||
surname: string;
|
||||
telephone: string;
|
||||
email: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
|
|
@ -44,6 +44,18 @@ export interface CreateCandidateLogin extends CreateCandidate {
|
|||
}
|
||||
|
||||
export const candidateData = writable<CandidateData>({
|
||||
candidate: {},
|
||||
candidate: {
|
||||
name: '',
|
||||
surname: '',
|
||||
birthplace: '',
|
||||
birthdate: '',
|
||||
address: '',
|
||||
telephone: '',
|
||||
citizenship: '',
|
||||
email: '',
|
||||
sex: '',
|
||||
study: '',
|
||||
personalIdNumber: ''
|
||||
},
|
||||
parents: []
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
import { apiFetchDetails, apiFetchSubmissionProgress } from '$lib/@api/candidate';
|
||||
import type { CandidateData } from '$lib/stores/candidate';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ fetch }) => {
|
||||
const details: CandidateData | undefined = await apiFetchDetails(fetch).catch((e) => {
|
||||
console.error(e);
|
||||
return undefined;
|
||||
});
|
||||
|
||||
return {
|
||||
candidate: details,
|
||||
};
|
||||
};
|
||||
|
|
@ -13,16 +13,23 @@
|
|||
import NameField from '$lib/components/textfield/NameField.svelte';
|
||||
import TelephoneField from '$lib/components/textfield/TelephoneField.svelte';
|
||||
import TextField from '$lib/components/textfield/TextField.svelte';
|
||||
import type { CandidateData } from '$lib/stores/candidate';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
import { createForm } from 'svelte-forms-lib';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import * as yup from 'yup';
|
||||
import type { CandidateData } from '$lib/stores/candidate';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
const pageCount = 5;
|
||||
let pageIndex = 0;
|
||||
let pagesFilled = [false, false, false, false, false];
|
||||
|
||||
export let data: PageData;
|
||||
let details = data.candidate;
|
||||
|
||||
let editMode = false;
|
||||
|
||||
const formInitialValues = {
|
||||
gdpr: false,
|
||||
candidate: {
|
||||
|
|
@ -108,43 +115,45 @@
|
|||
)
|
||||
});
|
||||
|
||||
const onSubmit = async (values: CandidateData) => {
|
||||
console.log('page count: ' + pageIndex);
|
||||
console.log(values.candidate);
|
||||
console.log(values.parents);
|
||||
console.log(values);
|
||||
if (pageIndex === pageCount) {
|
||||
// clone values to oldValues
|
||||
let oldValues = JSON.parse(JSON.stringify(values));
|
||||
try {
|
||||
console.log('submit');
|
||||
// @ts-ignore // love javascript
|
||||
delete values.undefined;
|
||||
// convert birthdate from dd.mm.yyyy to yyyy-mm-dd
|
||||
let birthdate_formttted = values.candidate
|
||||
.birthdate!.split('.')
|
||||
.map((x) => x.padStart(2, '0'))
|
||||
.reverse()
|
||||
.join('-');
|
||||
|
||||
values.candidate.birthdate = birthdate_formttted;
|
||||
|
||||
values.parents.filter(
|
||||
(x) => x.name !== '' && x.surname !== '' && x.email !== '' && x.telephone !== ''
|
||||
);
|
||||
|
||||
await apiFillDetails(values);
|
||||
goto('/dashboard');
|
||||
} catch (e) {
|
||||
values = oldValues;
|
||||
console.error('error while submitting data: ' + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const { form, errors, handleSubmit, handleChange } = createForm({
|
||||
initialValues: formInitialValues,
|
||||
validationSchema: formValidationSchema,
|
||||
|
||||
onSubmit: async (values: CandidateData) => {
|
||||
console.log('page count: ' + pageIndex);
|
||||
console.log(values.candidate);
|
||||
console.log(values.parents);
|
||||
console.log(values);
|
||||
if (pageIndex === pageCount) {
|
||||
// clone values to oldValues
|
||||
let oldValues = JSON.parse(JSON.stringify(values));
|
||||
try {
|
||||
console.log('submit');
|
||||
// @ts-ignore // love javascript
|
||||
delete values.undefined;
|
||||
// convert birthdate from dd.mm.yyyy to yyyy-mm-dd
|
||||
let birthdate_formttted = values.candidate
|
||||
.birthdate!.split('.')
|
||||
.map((x) => x.padStart(2, '0'))
|
||||
.reverse()
|
||||
.join('-');
|
||||
|
||||
values.candidate.birthdate = birthdate_formttted;
|
||||
|
||||
values.parents.filter(
|
||||
(x) => x.name !== '' && x.surname !== '' && x.email !== '' && x.telephone !== ''
|
||||
);
|
||||
|
||||
await apiFillDetails(values);
|
||||
goto('/dashboard');
|
||||
} catch (e) {
|
||||
values = oldValues;
|
||||
console.error('error while submitting data: ' + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
onSubmit: async (values: CandidateData) => onSubmit(values)
|
||||
});
|
||||
|
||||
type FormErrorType = {
|
||||
|
|
@ -163,8 +172,8 @@
|
|||
// TODO: https://github.com/tjinauyeung/svelte-forms-lib/issues/171!! (Zatím tenhle mega typ)
|
||||
$: typedErrors = errors as unknown as Writable<FormErrorType>;
|
||||
|
||||
const isPageInvalid = (): boolean => {
|
||||
switch (pageIndex) {
|
||||
const isPageInvalid = (index: number): boolean => {
|
||||
switch (index) {
|
||||
case 0:
|
||||
if ($typedErrors['gdpr']) {
|
||||
return true;
|
||||
|
|
@ -224,6 +233,52 @@
|
|||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const formatTelephone = (telephone: string) => {
|
||||
return '+' + telephone
|
||||
.match(/[0-9]{1,3}/g)!
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
$: console.log($form.candidate.birthdate);
|
||||
|
||||
if (details !== undefined) {
|
||||
details.candidate.birthdate = details.candidate.birthdate
|
||||
.split('-')
|
||||
.map((x) => x.startsWith('0') ? x.slice(1) : x)
|
||||
.reverse()
|
||||
.join('.');
|
||||
|
||||
details.candidate.telephone = formatTelephone(details.candidate.telephone);
|
||||
details.parents.map((x) => x.telephone = x.telephone != '' ? formatTelephone(x.telephone) : '');
|
||||
form.set({
|
||||
gdpr: true,
|
||||
candidate: {
|
||||
...details.candidate
|
||||
},
|
||||
parents: [
|
||||
{
|
||||
...details.parents[0]
|
||||
},
|
||||
{
|
||||
...details.parents[1] ?? {
|
||||
name: '',
|
||||
surname: '',
|
||||
email: '',
|
||||
telephone: ''
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
pageIndex = 1; // skip gdpr page
|
||||
}
|
||||
|
||||
// onMount(() => {
|
||||
// let evt: Event = document.createEvent('MouseEvent');
|
||||
// handleSubmit(evt);
|
||||
|
||||
// });
|
||||
|
||||
</script>
|
||||
|
||||
<SplitLayout>
|
||||
|
|
@ -231,8 +286,9 @@
|
|||
<div class="h-24 w-24 md:h-auto md:w-auto">
|
||||
<SchoolBadge />
|
||||
</div>
|
||||
<form on:submit={(e) => {handleSubmit(e); console.log("event" + e)}} id="triggerForm" class="invisible hidden"></form>
|
||||
{#if pageIndex === 0}
|
||||
<form on:submit={handleSubmit}>
|
||||
<form on:submit={(e) => {handleSubmit(e); console.log("event" + e)}}>
|
||||
<h1 class="text-sspsBlue mt-8 text-4xl font-semibold">Váš souhlas</h1>
|
||||
<p class="text-sspsGray mt-8 block text-center font-light">
|
||||
V rámci portálu pro přijímací řízení zpracováváme mnoho osobních údajů. Proto je nutný Váš
|
||||
|
|
@ -247,7 +303,7 @@
|
|||
</div>
|
||||
</form>
|
||||
{:else if pageIndex === 1}
|
||||
<form on:submit={handleSubmit}>
|
||||
<form on:submit={(e) => {handleSubmit(e); console.log("event" + e)}}>
|
||||
<h1 class="text-sspsBlue mt-8 text-4xl font-semibold">Registrace</h1>
|
||||
<p class="text-sspsGray mt-8 block text-center font-light">
|
||||
V rámci usnadnění přijímacího řízení jsme připravili online formulář, který vám pomůže s
|
||||
|
|
@ -452,9 +508,9 @@
|
|||
<div class="mt-8 w-full">
|
||||
<Submit
|
||||
on:click={async (e) => {
|
||||
console.log('event: ' + e);
|
||||
await handleSubmit(e);
|
||||
console.log('clicked ' + isPageInvalid());
|
||||
if (isPageInvalid()) return;
|
||||
if (isPageInvalid(pageIndex)) return;
|
||||
if (pageIndex === pageCount) {
|
||||
} else {
|
||||
pagesFilled[pageIndex] = true;
|
||||
|
|
@ -472,19 +528,24 @@
|
|||
<button
|
||||
class:dotActive={i === pageIndex}
|
||||
on:click={async (e) => {
|
||||
pageIndex -= pageIndex === pageCount ? 1 : 0;
|
||||
await handleSubmit(e);
|
||||
pagesFilled = pagesFilled.map((_, i) => !isPageInvalid(i));
|
||||
|
||||
const progress = pagesFilled.slice(0, i).every((item) => item === true);
|
||||
if (progress) {
|
||||
if (i > pageIndex) {
|
||||
// if next page is clicked, validate current page
|
||||
await handleSubmit(e);
|
||||
if (isPageInvalid()) return;
|
||||
pagesFilled[i] = true;
|
||||
pageIndex++;
|
||||
console.log($errors);
|
||||
if (isPageInvalid(pageIndex)) return;
|
||||
// pagesFilled[i] = true;
|
||||
console.log(pagesFilled);
|
||||
pageIndex = i;
|
||||
} else {
|
||||
pageIndex = i;
|
||||
}
|
||||
// @ts-ignore
|
||||
errors.set(formInitialValues);
|
||||
// errors.set(formInitialValues);
|
||||
}
|
||||
}}
|
||||
class="dot"
|
||||
|
|
|
|||
Loading…
Reference in a new issue