From d1fc6374b1d90910bfc56c2bf49bd2b5c707d532 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Sat, 21 Jan 2023 18:21:24 +0100 Subject: [PATCH 01/24] feat: bigger register views --- .../lib/components/layout/SplitLayout.svelte | 4 +- frontend/src/lib/stores/candidate.ts | 8 + .../[code=application]/+page.server.ts | 4 + .../(authenticated)/register/+page.svelte | 352 +++++++++--------- 4 files changed, 190 insertions(+), 178 deletions(-) diff --git a/frontend/src/lib/components/layout/SplitLayout.svelte b/frontend/src/lib/components/layout/SplitLayout.svelte index eeb618b..5726f5c 100644 --- a/frontend/src/lib/components/layout/SplitLayout.svelte +++ b/frontend/src/lib/components/layout/SplitLayout.svelte @@ -49,8 +49,8 @@ } .view { @apply z-10; - @apply absolute top-0 right-0 bottom-0 left-0 m-auto md:top-auto md:bottom-auto md:left-auto md:m-0; - @apply md:h-screen md:w-[50vw]; + @apply absolute top-0 right-0 bottom-0 m-auto md:top-auto md:bottom-auto md:left-auto md:m-0; + @apply md:h-screen md:w-[75vw]; @apply md:my-auto; @apply bg-white; } diff --git a/frontend/src/lib/stores/candidate.ts b/frontend/src/lib/stores/candidate.ts index 9b94cf8..7b22dc7 100644 --- a/frontend/src/lib/stores/candidate.ts +++ b/frontend/src/lib/stores/candidate.ts @@ -5,9 +5,11 @@ export interface CandidateData { candidate: { name: string; surname: string; + birthSurname: string; birthplace: string; birthdate: string; address: string; + letterAddress: string; telephone: string; citizenship: string; email: string; @@ -16,6 +18,8 @@ export interface CandidateData { schoolName: string; healthInsurance: string; grades: Array; + firstSchool: string; + secondSchool: string; testLanguage: string; }; parents: Array<{ @@ -66,9 +70,11 @@ export const candidateData = writable({ candidate: { name: '', surname: '', + birthSurname: '', birthplace: '', birthdate: '', address: '', + letterAddress: '', telephone: '', citizenship: '', email: '', @@ -77,6 +83,8 @@ export const candidateData = writable({ schoolName: '', healthInsurance: '', grades: [], + firstSchool: '', + secondSchool: '', testLanguage: '' }, parents: [] diff --git a/frontend/src/routes/(admin)/admin/(authenticated)/candidate/[code=application]/+page.server.ts b/frontend/src/routes/(admin)/admin/(authenticated)/candidate/[code=application]/+page.server.ts index 5088c69..ad436d9 100644 --- a/frontend/src/routes/(admin)/admin/(authenticated)/candidate/[code=application]/+page.server.ts +++ b/frontend/src/routes/(admin)/admin/(authenticated)/candidate/[code=application]/+page.server.ts @@ -10,9 +10,11 @@ export const load: PageServerLoad = async ({ fetch, params }) => { candidate: { name: '', surname: '', + birthSurname: '', birthplace: '', birthdate: '', address: '', + letterAddress: '', telephone: '', citizenship: '', email: '', @@ -21,6 +23,8 @@ export const load: PageServerLoad = async ({ fetch, params }) => { schoolName: '', healthInsurance: '', grades: [], + firstSchool: '', + secondSchool: '', testLanguage: '' }, parents: [] diff --git a/frontend/src/routes/(candidate)/(authenticated)/register/+page.svelte b/frontend/src/routes/(candidate)/(authenticated)/register/+page.svelte index f57d9b6..a27e294 100644 --- a/frontend/src/routes/(candidate)/(authenticated)/register/+page.svelte +++ b/frontend/src/routes/(candidate)/(authenticated)/register/+page.svelte @@ -23,9 +23,9 @@ import AccountLinkCheckBox from '$lib/components/checkbox/AccountLinkCheckBox.svelte'; import GradesTable from '$lib/components/grades/GradesTable.svelte'; - const pageCount = 7; let pageIndex = 0; - let pagesFilled = [false, false, false, false, false, false, false]; + let pagesFilled = [false, false, false, false, false, false]; + const pageCount = pagesFilled.length; let pageTexts = [ 'Zpracování osobních údajů', 'Registrace', @@ -39,6 +39,7 @@ let details = data.candidate; let baseCandidateDetails = data.whoami; + let personalIdBirthdateMatch = true; const formInitialValues = { gdpr: false, linkOk: false, @@ -46,12 +47,14 @@ candidate: { name: '', surname: '', + birthSurname: '', email: '', telephone: '', birthplace: '', birthdate: '', sex: '', address: '', + letterAddress: '', street: '', houseNumber: '', city: '', @@ -61,6 +64,8 @@ schoolName: '', healthInsurance: '', grades: [], + firstSchool: '', + secondSchool: '', testLanguage: '', }, parents: [ @@ -225,28 +230,31 @@ }; const onSubmit = async (values: CandidateData) => { + if (pageIndex === 3) { + if (values.candidate.citizenship === 'Česká republika') { + if ( + !isPersonalIdNumberWithBirthdateValid( + values.candidate.personalIdNumber, + values.candidate.birthdate + ) + ) { + toast.push('Rodné číslo neodpovídá oficiální specifikaci či datumu narození', { + theme: { + '--toastColor': 'mintcream', + '--toastBackground': '#b91c1c', + '--toastBarBackground': '#7f1d1d' + } + }); + personalIdBirthdateMatch = false; + throw new Error('Rodné číslo neodpovídá datumu narození'); + } + } + personalIdBirthdateMatch = true; + } if (pageIndex === pageCount) { // clone values to oldValues let oldValues = JSON.parse(JSON.stringify(values)); try { - if (values.candidate.citizenship === 'Česká republika') { - if ( - !isPersonalIdNumberWithBirthdateValid( - values.candidate.personalIdNumber, - values.candidate.birthdate - ) - ) { - // alert('Rodné číslo neodpovídá oficiální specifikaci či datumu narození'); // TODO: alerts - toast.push('Rodné číslo neodpovídá oficiální specifikaci či datumu narození', { - theme: { - '--toastColor': 'mintcream', - '--toastBackground': '#b91c1c', - '--toastBarBackground': '#7f1d1d' - } - }); - throw new Error('Rodné číslo neodpovídá datumu narození'); - } - } // @ts-ignore // love javascript delete values.undefined; // convert birthdate from dd.mm.yyyy to yyyy-mm-dd @@ -314,7 +322,11 @@ $typedErrors['candidate']['name'] || $typedErrors['candidate']['surname'] || $typedErrors['candidate']['email'] || - $typedErrors['candidate']['telephone'] + $typedErrors['candidate']['telephone'] || + $typedErrors['candidate']['city'] || + $typedErrors['candidate']['street'] || + $typedErrors['candidate']['houseNumber'] || + $typedErrors['candidate']['zip'] ) { return true; } @@ -322,13 +334,15 @@ case 3: if ( - $typedErrors['candidate']['birthplace'] || + $typedErrors['candidate']['citizenship'] || + $typedErrors['candidate']['personalIdNumber'] || + $typedErrors['candidate']['schoolName'] || + $typedErrors['candidate']['healthInsurance'] || $typedErrors['candidate']['birthdate'] || - $typedErrors['candidate']['street'] || - $typedErrors['candidate']['houseNumber'] || - $typedErrors['candidate']['city'] || - $typedErrors['candidate']['zip'] - // $typedErrors['candidate']['address'] + $typedErrors['candidate']['birthplace'] || + $typedErrors['candidate']['personalIdNumber'] || + $typedErrors['candidate']['testLanguage'] || + !personalIdBirthdateMatch ) { return true; } @@ -354,16 +368,6 @@ } break; case 6: - if ( - $typedErrors['candidate']['citizenship'] || - $typedErrors['candidate']['personalIdNumber'] || - $typedErrors['candidate']['schoolName'] || - $typedErrors['candidate']['healthInsurance'] - ) { - return true; - } - break; - case 7: if ($typedErrors["candidate"]["grades"].length > 0) return true; break; default: @@ -417,11 +421,11 @@ -
-
+
+
{#if pageIndex !== 0 && pageIndex !== 7} -
+
{/if} @@ -465,29 +469,72 @@ V rámci usnadnění přijímacího řízení jsme připravili online formulář, který Vám pomůže s vyplněním potřebných údajů.

-
- - - - - - - - - +
+
+
+ + + + + + +
+
+ + + + + + +
+ + + +
+
+ + + + + + +
{:else if pageIndex === 3} @@ -496,53 +543,24 @@ Pro registraci je potřeba vyplnit několik údajů o Vás. Tyto údaje budou použity pro přijímací řízení. Všechny údaje jsou důležité.

-
- - + + - - +
-
- - - - - -
- -
-
-
-
-
+ +
+
+ {#if $form.candidate.citizenship === 'Česká republika' || !$form.candidate.citizenship} + + {:else} + + {/if}
+
+ + {#if $form.candidate.citizenship === 'Česká republika' || !$form.candidate.citizenship} + + {:else} + + {/if} + + + + + +
+ {:else if pageIndex === 4}

{pageTexts[3]}

@@ -619,75 +688,6 @@

{:else if pageIndex === 6} -

{pageTexts[5]}

-

- Zadejte prosím své občanství, rodné číslo, či jeho alternativu Vaší země a obor na který - se hlásíte. -

-
-
- - - - - - -
-
- - {#if $form.candidate.citizenship === 'Česká republika' || !$form.candidate.citizenship} - - {:else} - - {/if} - - - - - -
-
-
- {#if $form.candidate.citizenship === 'Česká republika' || !$form.candidate.citizenship} - - {:else} - - {/if} -
- {:else if pageIndex === 7}

{pageTexts[5]}

Přidejte prosím přepis Vaších známek z posledních dvou let studia @@ -698,7 +698,7 @@ /> {/if}

-
+
{ @@ -716,7 +716,7 @@ />
-
+
{#each Array(pageCount + 1) as _, i}
{:else if pageIndex === 6} +

Přihlášky na školy

+
+ + + + + + +
+ {:else if pageIndex === 7}

{pageTexts[5]}

Přidejte prosím přepis Vaších známek z posledních dvou let studia From 0ece265827709b068fa74960b8640f1be3b73ee3 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Sun, 22 Jan 2023 19:24:56 +0100 Subject: [PATCH 04/24] fix: admin candidate view school type --- .../candidate/[code=application]/+page.server.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/routes/(admin)/admin/(authenticated)/candidate/[code=application]/+page.server.ts b/frontend/src/routes/(admin)/admin/(authenticated)/candidate/[code=application]/+page.server.ts index ad436d9..5bc7eea 100644 --- a/frontend/src/routes/(admin)/admin/(authenticated)/candidate/[code=application]/+page.server.ts +++ b/frontend/src/routes/(admin)/admin/(authenticated)/candidate/[code=application]/+page.server.ts @@ -23,8 +23,8 @@ export const load: PageServerLoad = async ({ fetch, params }) => { schoolName: '', healthInsurance: '', grades: [], - firstSchool: '', - secondSchool: '', + firstSchool: {name: '', field: ''}, + secondSchool: {name: '', field: ''}, testLanguage: '' }, parents: [] From 58b2a797b4b3d3af547b1808527590b5346b5c1a Mon Sep 17 00:00:00 2001 From: EETagent Date: Fri, 20 Jan 2023 13:12:42 +0100 Subject: [PATCH 05/24] feat: init typesafe-i18n --- frontend/.typesafe-i18n.json | 7 +++++ frontend/package.json | 4 ++- frontend/pnpm-lock.yaml | 13 +++++++- frontend/src/translations/cs/index.ts | 8 +++++ frontend/src/translations/de/index.ts | 8 +++++ frontend/src/translations/formatters.ts | 11 +++++++ frontend/src/translations/i18n-svelte.ts | 12 +++++++ frontend/src/translations/i18n-types.ts | 19 +++++++++++ frontend/src/translations/i18n-util.async.ts | 25 +++++++++++++++ frontend/src/translations/i18n-util.sync.ts | 21 +++++++++++++ frontend/src/translations/i18n-util.ts | 33 ++++++++++++++++++++ 11 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 frontend/.typesafe-i18n.json create mode 100644 frontend/src/translations/cs/index.ts create mode 100644 frontend/src/translations/de/index.ts create mode 100644 frontend/src/translations/formatters.ts create mode 100644 frontend/src/translations/i18n-svelte.ts create mode 100644 frontend/src/translations/i18n-types.ts create mode 100644 frontend/src/translations/i18n-util.async.ts create mode 100644 frontend/src/translations/i18n-util.sync.ts create mode 100644 frontend/src/translations/i18n-util.ts diff --git a/frontend/.typesafe-i18n.json b/frontend/.typesafe-i18n.json new file mode 100644 index 0000000..12eb8a1 --- /dev/null +++ b/frontend/.typesafe-i18n.json @@ -0,0 +1,7 @@ +{ + "baseLocale": "cs", + "adapter": "svelte", + "esmImports": true, + "outputPath": "./src/translations", + "$schema": "https://unpkg.com/typesafe-i18n@5.20.0/schema/typesafe-i18n.json" +} \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 2c1e416..f10de62 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,7 +10,8 @@ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "lint": "prettier --plugin-search-dir . --check . && eslint .", - "format": "prettier --plugin-search-dir . --write ." + "format": "prettier --plugin-search-dir . --write .", + "typesafe-i18n": "typesafe-i18n" }, "devDependencies": { "@playwright/test": "^1.29.2", @@ -46,6 +47,7 @@ "svelte-tippy": "^1.3.2", "swiper": "^8.4.6", "tippy.js": "^6.3.7", + "typesafe-i18n": "^5.20.0", "yup": "^0.32.11" } } diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index d76650e..774c62b 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -34,6 +34,9 @@ dependencies: tippy.js: specifier: ^6.3.7 version: 6.3.7 + typesafe-i18n: + specifier: ^5.20.0 + version: 5.20.0(typescript@4.9.4) yup: specifier: ^0.32.11 version: 0.32.11 @@ -2385,11 +2388,19 @@ packages: engines: {node: '>=10'} dev: true + /typesafe-i18n@5.20.0(typescript@4.9.4): + resolution: {integrity: sha512-uOvKnVkp1tXRDNBz9Aom54qs0LP2xWrtDliMPdKm9Scsnvn0DC7ZqjSGdOWxVplpbFbqYWNZuzx5Q5jWOjnBTA==} + hasBin: true + peerDependencies: + typescript: '>=3.5.1' + dependencies: + typescript: 4.9.4 + dev: false + /typescript@4.9.4: resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==} engines: {node: '>=4.2.0'} hasBin: true - dev: true /unconfig@0.2.2: resolution: {integrity: sha512-JN1MeYJ/POnjBj7NgOJJxPp6+NcD6Nd0hEuK0D89kjm9GvQQUq8HeE2Eb7PZgtu+64mWkDiqeJn1IZoLH7htPg==} diff --git a/frontend/src/translations/cs/index.ts b/frontend/src/translations/cs/index.ts new file mode 100644 index 0000000..71ee449 --- /dev/null +++ b/frontend/src/translations/cs/index.ts @@ -0,0 +1,8 @@ +import type { BaseTranslation } from '../i18n-types.js' + +const cs: BaseTranslation = { + // TODO: your translations go here + HI: 'Hi {name:string}! Please leave a star if you like this project: https://github.com/ivanhofer/typesafe-i18n', +} + +export default cs diff --git a/frontend/src/translations/de/index.ts b/frontend/src/translations/de/index.ts new file mode 100644 index 0000000..eaae244 --- /dev/null +++ b/frontend/src/translations/de/index.ts @@ -0,0 +1,8 @@ +import type { Translation } from '../i18n-types.js' + +const de: Translation = { + // this is an example Translation, just rename or delete this folder if you want + HI: 'Hallo {name}! Bitte hinterlasse einen Stern, wenn dir das Projekt gefällt: https://github.com/ivanhofer/typesafe-i18n', +} + +export default de diff --git a/frontend/src/translations/formatters.ts b/frontend/src/translations/formatters.ts new file mode 100644 index 0000000..9e0741e --- /dev/null +++ b/frontend/src/translations/formatters.ts @@ -0,0 +1,11 @@ +import type { FormattersInitializer } from 'typesafe-i18n' +import type { Locales, Formatters } from './i18n-types.js' + +export const initFormatters: FormattersInitializer = (locale: Locales) => { + + const formatters: Formatters = { + // add your formatter functions here + } + + return formatters +} diff --git a/frontend/src/translations/i18n-svelte.ts b/frontend/src/translations/i18n-svelte.ts new file mode 100644 index 0000000..23d478d --- /dev/null +++ b/frontend/src/translations/i18n-svelte.ts @@ -0,0 +1,12 @@ +// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten. +/* eslint-disable */ + +import { initI18nSvelte } from 'typesafe-i18n/svelte' +import type { Formatters, Locales, TranslationFunctions, Translations } from './i18n-types.js' +import { loadedFormatters, loadedLocales } from './i18n-util.js' + +const { locale, LL, setLocale } = initI18nSvelte(loadedLocales, loadedFormatters) + +export { locale, LL, setLocale } + +export default LL diff --git a/frontend/src/translations/i18n-types.ts b/frontend/src/translations/i18n-types.ts new file mode 100644 index 0000000..9ae0378 --- /dev/null +++ b/frontend/src/translations/i18n-types.ts @@ -0,0 +1,19 @@ +// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten. +/* eslint-disable */ +import type { BaseTranslation as BaseTranslationType } from 'typesafe-i18n' + +export type BaseTranslation = BaseTranslationType +export type BaseLocale = 'cs' + +export type Locales = + | 'cs' + +export type Translation = RootTranslation + +export type Translations = RootTranslation + +type RootTranslation = {} + +export type TranslationFunctions = {} + +export type Formatters = {} diff --git a/frontend/src/translations/i18n-util.async.ts b/frontend/src/translations/i18n-util.async.ts new file mode 100644 index 0000000..5d4505a --- /dev/null +++ b/frontend/src/translations/i18n-util.async.ts @@ -0,0 +1,25 @@ +// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten. +/* eslint-disable */ + +import { initFormatters } from './formatters.js' +import type { Locales, Translations } from './i18n-types.js' +import { loadedFormatters, loadedLocales, locales } from './i18n-util.js' + +const localeTranslationLoaders = { +} + +const updateDictionary = (locale: Locales, dictionary: Partial): Translations => + loadedLocales[locale] = { ...loadedLocales[locale], ...dictionary } + +export const importLocaleAsync = async (locale: Locales): Promise => + (await localeTranslationLoaders[locale]()).default as unknown as Translations + +export const loadLocaleAsync = async (locale: Locales): Promise => { + updateDictionary(locale, await importLocaleAsync(locale)) + loadFormatters(locale) +} + +export const loadAllLocalesAsync = (): Promise => Promise.all(locales.map(loadLocaleAsync)) + +export const loadFormatters = (locale: Locales): void => + void (loadedFormatters[locale] = initFormatters(locale)) diff --git a/frontend/src/translations/i18n-util.sync.ts b/frontend/src/translations/i18n-util.sync.ts new file mode 100644 index 0000000..523c1eb --- /dev/null +++ b/frontend/src/translations/i18n-util.sync.ts @@ -0,0 +1,21 @@ +// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten. +/* eslint-disable */ + +import { initFormatters } from './formatters.js' +import type { Locales, Translations } from './i18n-types.js' +import { loadedFormatters, loadedLocales, locales } from './i18n-util.js' + +const localeTranslations = { +} + +export const loadLocale = (locale: Locales): void => { + if (loadedLocales[locale]) return + + loadedLocales[locale] = localeTranslations[locale] as unknown as Translations + loadFormatters(locale) +} + +export const loadAllLocales = (): void => locales.forEach(loadLocale) + +export const loadFormatters = (locale: Locales): void => + void (loadedFormatters[locale] = initFormatters(locale)) diff --git a/frontend/src/translations/i18n-util.ts b/frontend/src/translations/i18n-util.ts new file mode 100644 index 0000000..109c3be --- /dev/null +++ b/frontend/src/translations/i18n-util.ts @@ -0,0 +1,33 @@ +// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten. +/* eslint-disable */ + +import { i18n as initI18n, i18nObject as initI18nObject, i18nString as initI18nString } from 'typesafe-i18n' +import type { LocaleDetector } from 'typesafe-i18n/detectors' +import type { LocaleTranslationFunctions, TranslateByString } from 'typesafe-i18n' +import { detectLocale as detectLocaleFn } from 'typesafe-i18n/detectors' +import type { Formatters, Locales, Translations, TranslationFunctions } from './i18n-types.js' + +export const baseLocale: Locales = 'cs' + +export const locales: Locales[] = [ +] + +export const isLocale = (locale: string): locale is Locales => locales.includes(locale as Locales) + +export const loadedLocales: Record = {} as Record + +export const loadedFormatters: Record = {} as Record + +export const i18nString = (locale: Locales): TranslateByString => initI18nString(locale, loadedFormatters[locale]) + +export const i18nObject = (locale: Locales): TranslationFunctions => + initI18nObject( + locale, + loadedLocales[locale], + loadedFormatters[locale] + ) + +export const i18n = (): LocaleTranslationFunctions => + initI18n(loadedLocales, loadedFormatters) + +export const detectLocale = (...detectors: LocaleDetector[]): Locales => detectLocaleFn(baseLocale, locales, ...detectors) From c0126bd740c4a96401973a9ee3c22557bed8cb94 Mon Sep 17 00:00:00 2001 From: EETagent Date: Fri, 20 Jan 2023 13:12:56 +0100 Subject: [PATCH 06/24] chore: add VSCode i18n ally settings --- .../.vscode/i18n-ally-custom-framework.yml | 18 ++++++++++++++++++ frontend/.vscode/settings.json | 6 ++++++ 2 files changed, 24 insertions(+) create mode 100644 frontend/.vscode/i18n-ally-custom-framework.yml create mode 100644 frontend/.vscode/settings.json diff --git a/frontend/.vscode/i18n-ally-custom-framework.yml b/frontend/.vscode/i18n-ally-custom-framework.yml new file mode 100644 index 0000000..c17d03b --- /dev/null +++ b/frontend/.vscode/i18n-ally-custom-framework.yml @@ -0,0 +1,18 @@ +languageIds: + - typescript + - javascript + - typescriptreact + - javascriptreact + - svelte + - html + +usageMatchRegex: + - "\\$?LL\\.({key})\\(((\\{.*\\})|([^)]*))\\)" + +refactorTemplates: + - '{$LL.$1()}' + - '{LL.$1()}' + - '$LL.$1()' + - 'LL.$1()' + +monopoly: true diff --git a/frontend/.vscode/settings.json b/frontend/.vscode/settings.json new file mode 100644 index 0000000..c7be7fc --- /dev/null +++ b/frontend/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "i18n-ally.pathMatcher": "{locale}/index.{ext}", + "i18n-ally.enabledParsers": ["ts", "js"], + "i18n-ally.keystyle": "nested", + "i18n-ally.localesPaths": ["src/translations"] +} From 5a55f73154f77660c6eed518085eb8935efdddcd Mon Sep 17 00:00:00 2001 From: EETagent Date: Fri, 20 Jan 2023 13:19:11 +0100 Subject: [PATCH 07/24] =?UTF-8?q?feat:=20deportace=20N=C4=9Bmc=C5=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/translations/cs/index.ts | 2 -- frontend/src/translations/de/index.ts | 8 -------- frontend/src/translations/i18n-util.async.ts | 1 + frontend/src/translations/i18n-util.sync.ts | 3 +++ frontend/src/translations/i18n-util.ts | 1 + 5 files changed, 5 insertions(+), 10 deletions(-) delete mode 100644 frontend/src/translations/de/index.ts diff --git a/frontend/src/translations/cs/index.ts b/frontend/src/translations/cs/index.ts index 71ee449..7c0994b 100644 --- a/frontend/src/translations/cs/index.ts +++ b/frontend/src/translations/cs/index.ts @@ -1,8 +1,6 @@ import type { BaseTranslation } from '../i18n-types.js' const cs: BaseTranslation = { - // TODO: your translations go here - HI: 'Hi {name:string}! Please leave a star if you like this project: https://github.com/ivanhofer/typesafe-i18n', } export default cs diff --git a/frontend/src/translations/de/index.ts b/frontend/src/translations/de/index.ts deleted file mode 100644 index eaae244..0000000 --- a/frontend/src/translations/de/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Translation } from '../i18n-types.js' - -const de: Translation = { - // this is an example Translation, just rename or delete this folder if you want - HI: 'Hallo {name}! Bitte hinterlasse einen Stern, wenn dir das Projekt gefällt: https://github.com/ivanhofer/typesafe-i18n', -} - -export default de diff --git a/frontend/src/translations/i18n-util.async.ts b/frontend/src/translations/i18n-util.async.ts index 5d4505a..e9e06f8 100644 --- a/frontend/src/translations/i18n-util.async.ts +++ b/frontend/src/translations/i18n-util.async.ts @@ -6,6 +6,7 @@ import type { Locales, Translations } from './i18n-types.js' import { loadedFormatters, loadedLocales, locales } from './i18n-util.js' const localeTranslationLoaders = { + cs: () => import('./cs/index.js'), } const updateDictionary = (locale: Locales, dictionary: Partial): Translations => diff --git a/frontend/src/translations/i18n-util.sync.ts b/frontend/src/translations/i18n-util.sync.ts index 523c1eb..5ad0a1d 100644 --- a/frontend/src/translations/i18n-util.sync.ts +++ b/frontend/src/translations/i18n-util.sync.ts @@ -5,7 +5,10 @@ import { initFormatters } from './formatters.js' import type { Locales, Translations } from './i18n-types.js' import { loadedFormatters, loadedLocales, locales } from './i18n-util.js' +import cs from './cs/index.js' + const localeTranslations = { + cs, } export const loadLocale = (locale: Locales): void => { diff --git a/frontend/src/translations/i18n-util.ts b/frontend/src/translations/i18n-util.ts index 109c3be..bbd277a 100644 --- a/frontend/src/translations/i18n-util.ts +++ b/frontend/src/translations/i18n-util.ts @@ -10,6 +10,7 @@ import type { Formatters, Locales, Translations, TranslationFunctions } from './ export const baseLocale: Locales = 'cs' export const locales: Locales[] = [ + 'cs' ] export const isLocale = (locale: string): locale is Locales => locales.includes(locale as Locales) From ff3af6bed1b4bde01fe3736dc34d4affefd92009 Mon Sep 17 00:00:00 2001 From: EETagent Date: Fri, 20 Jan 2023 13:23:35 +0100 Subject: [PATCH 08/24] feat: aliases for paths --- frontend/svelte.config.js | 7 ++++++- frontend/tsconfig.json | 9 ++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/frontend/svelte.config.js b/frontend/svelte.config.js index 2ef33af..a3f4721 100644 --- a/frontend/svelte.config.js +++ b/frontend/svelte.config.js @@ -1,5 +1,6 @@ import adapter from '@sveltejs/adapter-node'; import preprocess from 'svelte-preprocess'; +import path from "path"; import { windi } from 'svelte-windicss-preprocess'; /** @type {import('@sveltejs/kit').Config} */ @@ -8,7 +9,11 @@ const config = { // for more information about preprocessors preprocess: [preprocess(), windi({})], kit: { - adapter: adapter({ out: 'build' }) + adapter: adapter({ out: 'build' }), + alias: { + $i18n: path.resolve('./src/translations'), + } + } }; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 8793475..7176a96 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -9,6 +9,13 @@ "resolveJsonModule": true, "skipLibCheck": true, "sourceMap": true, - "strict": true + "strict": true, + "paths": { + "$lib": ["src/lib"], + "$lib/*": ["src/lib/*"], + "$i18n": ["src/translations"], + "$i18n/*": ["src/translations/*"], + "$params": ["src/params"], + } } } From a4d1399c9a9f0e8fb61a33212cb7c944418733fd Mon Sep 17 00:00:00 2001 From: EETagent Date: Fri, 20 Jan 2023 14:13:54 +0100 Subject: [PATCH 09/24] chore: remove broken config overrides --- .../.vscode/i18n-ally-custom-framework.yml | 18 ------------------ frontend/.vscode/settings.json | 6 ------ 2 files changed, 24 deletions(-) delete mode 100644 frontend/.vscode/i18n-ally-custom-framework.yml delete mode 100644 frontend/.vscode/settings.json diff --git a/frontend/.vscode/i18n-ally-custom-framework.yml b/frontend/.vscode/i18n-ally-custom-framework.yml deleted file mode 100644 index c17d03b..0000000 --- a/frontend/.vscode/i18n-ally-custom-framework.yml +++ /dev/null @@ -1,18 +0,0 @@ -languageIds: - - typescript - - javascript - - typescriptreact - - javascriptreact - - svelte - - html - -usageMatchRegex: - - "\\$?LL\\.({key})\\(((\\{.*\\})|([^)]*))\\)" - -refactorTemplates: - - '{$LL.$1()}' - - '{LL.$1()}' - - '$LL.$1()' - - 'LL.$1()' - -monopoly: true diff --git a/frontend/.vscode/settings.json b/frontend/.vscode/settings.json deleted file mode 100644 index c7be7fc..0000000 --- a/frontend/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "i18n-ally.pathMatcher": "{locale}/index.{ext}", - "i18n-ally.enabledParsers": ["ts", "js"], - "i18n-ally.keystyle": "nested", - "i18n-ally.localesPaths": ["src/translations"] -} From 51e9275ba6e75f2dec0248fec861a5abfe02da5e Mon Sep 17 00:00:00 2001 From: EETagent Date: Fri, 20 Jan 2023 14:14:07 +0100 Subject: [PATCH 10/24] chore: fix tsconfig --- frontend/tsconfig.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 7176a96..ab896ad 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -10,12 +10,5 @@ "skipLibCheck": true, "sourceMap": true, "strict": true, - "paths": { - "$lib": ["src/lib"], - "$lib/*": ["src/lib/*"], - "$i18n": ["src/translations"], - "$i18n/*": ["src/translations/*"], - "$params": ["src/params"], - } } } From cdb27d79da9ad476c68eb8e6b0316b4940950de9 Mon Sep 17 00:00:00 2001 From: EETagent Date: Fri, 20 Jan 2023 14:14:19 +0100 Subject: [PATCH 11/24] feat? initial translation --- .../(candidate)/auth/login/+page.svelte | 6 +-- frontend/src/translations/cs/index.ts | 15 ++++++-- frontend/src/translations/i18n-types.ts | 38 +++++++++++++++++-- 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/frontend/src/routes/(candidate)/auth/login/+page.svelte b/frontend/src/routes/(candidate)/auth/login/+page.svelte index cff8cc5..3f1bd4c 100644 --- a/frontend/src/routes/(candidate)/auth/login/+page.svelte +++ b/frontend/src/routes/(candidate)/auth/login/+page.svelte @@ -1,4 +1,5 @@ @@ -431,10 +432,9 @@

- {:else if pageIndex === 3} + {:else if pageIndex === 4}

{pageTexts[2]}

Pro registraci je potřeba vyplnit několik údajů o Vás. Tyto údaje budou použity pro @@ -644,7 +628,7 @@

- {:else if pageIndex === 4} + {:else if pageIndex === 5}

{pageTexts[3]}

{$LL.candidate.register.fifth.description()} @@ -673,7 +657,7 @@ />

- {:else if pageIndex === 5} + {:else if pageIndex === 6}

{pageTexts[4]}

{$LL.candidate.register.sixth.description()} @@ -702,7 +686,7 @@ />

- {:else if pageIndex === 6} + {:else if pageIndex === 7}

Přihlášky na školy

@@ -712,7 +696,7 @@
- {:else if pageIndex === 7} + {:else if pageIndex === 8}

{pageTexts[6]}

{$LL.candidate.register.eighth.description()} diff --git a/frontend/src/translations/cs/index.ts b/frontend/src/translations/cs/index.ts index 3c499a4..57d00d9 100644 --- a/frontend/src/translations/cs/index.ts +++ b/frontend/src/translations/cs/index.ts @@ -83,6 +83,12 @@ const cs: BaseTranslation = { title2: 'Ne, přihlášku na SSPŠaG jsem podával více přihlášek' } }, + personalIdConfirmCheckBox: { + ok: 'Vše je v pořádku', + whatHappened: 'Co se děje?', + titleOk: 'Potvrzuji, že moje rodné číslo je {personalId}', + titleErr: 'Ne, moje rodné číslo není {personalId}', + }, gdprCheckBox: { title: 'Souhlasím se zpracováním osobních údajů', description: 'Kliknutím vyjaďřujete souhlas se zpracováním osobních údajů', diff --git a/frontend/src/translations/i18n-types.ts b/frontend/src/translations/i18n-types.ts index 0e54064..564d585 100644 --- a/frontend/src/translations/i18n-types.ts +++ b/frontend/src/translations/i18n-types.ts @@ -185,6 +185,26 @@ type RootTranslation = { title2: string } } + personalIdConfirmCheckBox: { + /** + * V​š​e​ ​j​e​ ​v​ ​p​o​ř​á​d​k​u + */ + ok: string + /** + * C​o​ ​s​e​ ​d​ě​j​e​? + */ + whatHappened: string + /** + * P​o​t​v​r​z​u​j​i​,​ ​ž​e​ ​m​o​j​e​ ​r​o​d​n​é​ ​č​í​s​l​o​ ​j​e​ ​{​p​e​r​s​o​n​a​l​I​d​} + * @param {unknown} personalId + */ + titleOk: RequiredParams<'personalId'> + /** + * N​e​,​ ​m​o​j​e​ ​r​o​d​n​é​ ​č​í​s​l​o​ ​n​e​n​í​ ​{​p​e​r​s​o​n​a​l​I​d​} + * @param {unknown} personalId + */ + titleErr: RequiredParams<'personalId'> + } gdprCheckBox: { /** * S​o​u​h​l​a​s​í​m​ ​s​e​ ​z​p​r​a​c​o​v​á​n​í​m​ ​o​s​o​b​n​í​c​h​ ​ú​d​a​j​ů @@ -472,6 +492,24 @@ export type TranslationFunctions = { title2: () => LocalizedString } } + personalIdConfirmCheckBox: { + /** + * Vše je v pořádku + */ + ok: () => LocalizedString + /** + * Co se děje? + */ + whatHappened: () => LocalizedString + /** + * Potvrzuji, že moje rodné číslo je {personalId} + */ + titleOk: (arg: { personalId: unknown }) => LocalizedString + /** + * Ne, moje rodné číslo není {personalId} + */ + titleErr: (arg: { personalId: unknown }) => LocalizedString + } gdprCheckBox: { /** * Souhlasím se zpracováním osobních údajů From d3ff293224503f70786c6c59a3746fba525a3b1a Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Wed, 25 Jan 2023 11:32:18 +0100 Subject: [PATCH 19/24] feat: application create - more detailed response --- api/src/routes/admin.rs | 16 ++++++++-- core/src/models/candidate.rs | 2 ++ core/src/services/application_service.rs | 38 ++++++++++++++++++------ core/src/services/candidate_service.rs | 2 +- core/src/services/session_service.rs | 6 ++-- 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/api/src/routes/admin.rs b/api/src/routes/admin.rs index 1310511..8de69b6 100644 --- a/api/src/routes/admin.rs +++ b/api/src/routes/admin.rs @@ -94,15 +94,25 @@ pub async fn create_candidate( let plain_text_password = random_12_char_string(); - ApplicationService::create(&private_key, &db, form.application_id, &plain_text_password, form.personal_id_number.clone()) + let (application, applications, personal_id_number) = ApplicationService::create( + &private_key, + &db, + form.application_id, + &plain_text_password, + form.personal_id_number.clone() + ) .await .map_err(to_custom_error)?; Ok( Json( CreateCandidateResponse { - application_id: form.application_id, - personal_id_number: form.personal_id_number, + application_id: application.id, + field_of_study: application.field_of_study, + applications: applications.iter() + .map(|a| a.id) + .collect(), + personal_id_number, password: plain_text_password, } ) diff --git a/core/src/models/candidate.rs b/core/src/models/candidate.rs index 521cade..08a16ae 100644 --- a/core/src/models/candidate.rs +++ b/core/src/models/candidate.rs @@ -54,6 +54,8 @@ pub struct NewCandidateResponse { #[serde(rename_all = "camelCase")] pub struct CreateCandidateResponse { pub application_id: i32, + pub field_of_study: String, + pub applications: Vec, pub personal_id_number: String, pub password: String, } diff --git a/core/src/services/application_service.rs b/core/src/services/application_service.rs index 991184c..9e80fff 100644 --- a/core/src/services/application_service.rs +++ b/core/src/services/application_service.rs @@ -24,7 +24,7 @@ impl ApplicationService { application_id: i32, plain_text_password: &String, personal_id_number: String, - ) -> Result { + ) -> Result<(application::Model, Vec, String), ServiceError> { // Check if application id starts with 101, 102 or 103 if !Self::is_application_id_valid(application_id) { return Err(ServiceError::InvalidApplicationId); @@ -50,7 +50,7 @@ impl ApplicationService { application_id, admin_private_key, db, - personal_id_number, + &personal_id_number, &pubkey, ).await?; @@ -72,15 +72,31 @@ impl ApplicationService { } return Err(ServiceError::InternalServerError); } - - Ok(application) + Ok( + /* NewCandidateResponse { + current_application: application.id, + applications: applications + .iter() + .map(|a| a.id) + .collect::>(), + details_filled: false, + encrypted_by: Some(application.id), + field_of_study: application.field_of_study, + personal_id_number: personal_id_number, + } */ + ( + application, + applications, + personal_id_number, + ) + ) } async fn find_or_create_candidate_with_personal_id( application_id: i32, admin_private_key: &String, db: &DbConn, - personal_id_number: String, + personal_id_number: &String, pubkey: &String, // enc_personal_id_number: &EncryptedString, ) -> Result<(candidate::Model, String), ServiceError> { @@ -98,7 +114,7 @@ impl ApplicationService { let found_ids: Vec<&(i32, String)> = ids_decrypted .iter() - .filter(|(_, id)| id == &personal_id_number) + .filter(|(_, id)| id == personal_id_number) .collect(); if let Some((candidate_id, _)) = found_ids.first() { @@ -107,14 +123,14 @@ impl ApplicationService { application_id, *candidate_id, pubkey, - personal_id_number + personal_id_number.to_owned() ).await? ) } else { let recipients = get_recipients(db, pubkey).await?; let enc_personal_id_number = EncryptedString::new( - &personal_id_number, + personal_id_number, &recipients, ).await?; Ok( @@ -354,6 +370,10 @@ impl ApplicationService { Ok( CreateCandidateResponse { application_id: id, + field_of_study: application.field_of_study, + applications: applications.iter() + .map(|a| a.id) + .collect(), personal_id_number, password: new_password_plain, } @@ -489,7 +509,7 @@ mod application_tests { let secret_message = "trnka".to_string(); - let application = ApplicationService::create(&"".to_string(), &db, 103100, &plain_text_password, "".to_string()).await.unwrap(); + let application = ApplicationService::create(&"".to_string(), &db, 103100, &plain_text_password, "".to_string()).await.unwrap().0; let encrypted_message = crypto::encrypt_password_with_recipients(&secret_message, &vec![&application.public_key]) diff --git a/core/src/services/candidate_service.rs b/core/src/services/candidate_service.rs index 223b8c1..628b6be 100644 --- a/core/src/services/candidate_service.rs +++ b/core/src/services/candidate_service.rs @@ -99,7 +99,7 @@ pub mod tests { APPLICATION_ID, &plain_text_password, "0000001111".to_string() - ).await.unwrap(); + ).await.unwrap().0; let candidate= ApplicationService::find_related_candidate(db, &application).await.unwrap(); ParentService::create(db, candidate.id).await.unwrap(); diff --git a/core/src/services/session_service.rs b/core/src/services/session_service.rs index eacc31d..0cb3489 100644 --- a/core/src/services/session_service.rs +++ b/core/src/services/session_service.rs @@ -52,7 +52,7 @@ mod tests { let db = get_memory_sqlite_connection().await; - let application = ApplicationService::create(&"".to_string(), &db, 103151, &SECRET.to_string(), "".to_string()).await.unwrap(); + let application = ApplicationService::create(&"".to_string(), &db, 103151, &SECRET.to_string(), "".to_string()).await.unwrap().0; assert_eq!(application.id.to_owned(), 103151); assert_ne!(application.password.to_owned(), SECRET.to_string()); @@ -66,7 +66,7 @@ mod tests { async fn test_candidate_session_correct_password() { let db = &get_memory_sqlite_connection().await; - let application = ApplicationService::create(&"".to_string(), &db, 103151, &SECRET.to_string(), "".to_string()).await.unwrap(); + let application = ApplicationService::create(&"".to_string(), &db, 103151, &SECRET.to_string(), "".to_string()).await.unwrap().0; // correct password let session = ApplicationService::new_session( @@ -88,7 +88,7 @@ mod tests { async fn test_candidate_session_incorrect_password() { let db = &get_memory_sqlite_connection().await; - let application = ApplicationService::create(&"".to_string(), &db, 103151, &SECRET.to_string(), "".to_string()).await.unwrap(); + let application = ApplicationService::create(&"".to_string(), &db, 103151, &SECRET.to_string(), "".to_string()).await.unwrap().0; // incorrect password assert!(ApplicationService::new_session( From f8bc1295a0913cda4430e18cba21585f9a58328b Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Wed, 25 Jan 2023 11:32:50 +0100 Subject: [PATCH 20/24] feat: CreateCandidateModal input validation --- .../admin/modal/CreateCandidateModal.svelte | 88 +++++++++++++++++-- frontend/src/lib/stores/candidate.ts | 2 + 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/frontend/src/lib/components/admin/modal/CreateCandidateModal.svelte b/frontend/src/lib/components/admin/modal/CreateCandidateModal.svelte index c6df9dc..8f66eb7 100644 --- a/frontend/src/lib/components/admin/modal/CreateCandidateModal.svelte +++ b/frontend/src/lib/components/admin/modal/CreateCandidateModal.svelte @@ -1,16 +1,22 @@ {#if isOpened} +

{#if login} -

{applicationId}

-

{login.password}

+

Ev. č.: {applicationId}

+

R. č.: {login.personalIdNumber}

+

Heslo: {login.password}

+ {#if login.applications.length > 1} +

+ Slinkovaný s {login.applications.filter((a) => a != applicationId)} +

+ {/if} {:else}

Registrace nového uchazeče

{#if error} @@ -55,10 +113,28 @@ {error}
{/if} -

Evidenčni číslo přihlášky

- -

Rodné číslo

- +
+

Evidenční číslo přihlášky ( + {`Obor: ${field}`}) +

+ +
+
+

Občanství

+ +

Rodné číslo

+
+
+ {#if citizenship === 'Česká republika'} + + {:else} + + {/if} +
Date: Wed, 25 Jan 2023 22:06:38 +0100 Subject: [PATCH 21/24] fix: svelte check --- frontend/src/lib/components/select/SchoolSelect.svelte | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend/src/lib/components/select/SchoolSelect.svelte b/frontend/src/lib/components/select/SchoolSelect.svelte index 1b33f7c..d569070 100644 --- a/frontend/src/lib/components/select/SchoolSelect.svelte +++ b/frontend/src/lib/components/select/SchoolSelect.svelte @@ -1,6 +1,7 @@ \ No newline at end of file diff --git a/frontend/src/lib/components/select/SchoolSelect.svelte b/frontend/src/lib/components/select/SchoolSelect.svelte deleted file mode 100644 index d569070..0000000 --- a/frontend/src/lib/components/select/SchoolSelect.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - -
-
- - Selected school: {selectedSchool.name} - - - - -
-
- Obor: - -
-
\ No newline at end of file