From 449f67c2a086774b6eef6d8ee29a48ce7f3a4ff1 Mon Sep 17 00:00:00 2001 From: matthieu42morin Date: Wed, 20 Mar 2024 16:11:46 +0100 Subject: [PATCH] Services OVERHAUL =>> using json with schemas and validators as database --- package.json | 18 +++-- src/content/services/dalsi-sluzby.json | 34 +++++++++ src/content/services/depilace.json | 69 +++++++++++++++++ src/content/services/kosmeticke-osetreni.json | 48 ++++++++++++ src/content/services/permanent-mu.json | 69 +++++++++++++++++ src/content/services/vakuslim.json | 41 ++++++++++ src/routes/sluzby/schema.json | 74 +++++++++++++++++++ tests/ValidateServices.js | 41 ++++++++++ 8 files changed, 386 insertions(+), 8 deletions(-) create mode 100644 src/content/services/dalsi-sluzby.json create mode 100644 src/content/services/depilace.json create mode 100644 src/content/services/kosmeticke-osetreni.json create mode 100644 src/content/services/permanent-mu.json create mode 100644 src/content/services/vakuslim.json create mode 100644 src/routes/sluzby/schema.json create mode 100644 tests/ValidateServices.js diff --git a/package.json b/package.json index c127616..286914e 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,15 @@ { - "name": "cosmeticstudio", + "name": "kkosmetickysalon", "version": "0.0.1", "private": true, + "type": "module", "scripts": { - "dev": "vite dev --mode development", - "build": "vite build", - "build-dev": "vite build --mode development", + "validate": "node ./tests/ValidateServices.js", + "dev": "pnpm run validate && vite dev --mode development", + "build": "pnpm run validate && vite build", + "build-dev": "pnpm run validate && vite build --mode development", "preview": "vite preview", - "test": "npm run test:integration && npm run test:unit", + "test": "pnpm run test:integration && npm run test:unit", "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 .", @@ -23,7 +25,8 @@ "@fortawesome/fontawesome-free": "^6.5.1", "@sentry/sveltekit": "^7.107.0", "@sveltejs/adapter-node": "^5.0.1", - "@sveltejs/vite-plugin-svelte": "^3.0.2" + "@sveltejs/vite-plugin-svelte": "^3.0.2", + "ajv": "^8.12.0" }, "devDependencies": { "@floating-ui/dom": "1.5.3", @@ -53,6 +56,5 @@ "vite": "^5.1.6", "vite-plugin-tailwind-purgecss": "^0.2.0", "vitest": "^0.32.4" - }, - "type": "module" + } } diff --git a/src/content/services/dalsi-sluzby.json b/src/content/services/dalsi-sluzby.json new file mode 100644 index 0000000..82b4962 --- /dev/null +++ b/src/content/services/dalsi-sluzby.json @@ -0,0 +1,34 @@ +{ + "$schema": "/src/routes/sluzby/schema.json", + "category": "DALŠÍ VELMI OBLÍBENÉ SLUŽBY", + "items": [ + { + "name": "Lifting řas booster (botox)", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "lifting-ras-booster", + "price": 500, + "duration": 1 + }, + { + "name": "Laminace obočí + výživa", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "laminace-oboci-vyziva", + "price": 500, + "duration": 1 + }, + { + "name": "Úprava obočí (tvar + barva)", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "uprava-oboci-tvar-barva", + "price": 250, + "duration": 1 + }, + { + "name": "Úprava obočí + řasy (tvar + barvení)", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "uprava-oboci-rasy-tvar-barveni", + "price": 300, + "duration": 1 + } + ] +} diff --git a/src/content/services/depilace.json b/src/content/services/depilace.json new file mode 100644 index 0000000..feab20e --- /dev/null +++ b/src/content/services/depilace.json @@ -0,0 +1,69 @@ +{ + "$schema": "/src/routes/sluzby/schema.json", + "category": "Depilace", + "items": [ + { + "name": "Depilace Horní ret", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "depilace-horni-ret", + "price": 80, + "duration": 0.5 + }, + { + "name": "Depilace Brada", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "depilace-brada", + "price": 80, + "duration": 0.5 + }, + { + "name": "Depilace Obočí", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "depilace-oboci", + "price": 150, + "duration": 0.5 + }, + { + "name": "Depilace Tváře", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "depilace-tvare", + "price": 150, + "duration": 0.5 + }, + { + "name": "Depilace Podpaží", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "depilace-podpazi", + "price": 150, + "duration": 0.5 + }, + { + "name": "Depilace Předloktí", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "depilace-predlokti", + "price": 200, + "duration": 0.5 + }, + { + "name": "Depilace Celé ruce", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "depilace-cele-ruce", + "price": 350, + "duration": 1 + }, + { + "name": "Depilace Lýtka", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "depilace-lytka", + "price": 350, + "duration": 1 + }, + { + "name": "Depilace Celé nohy", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "depilace-cele-nohy", + "price": 500, + "duration": 1 + } + ] +} diff --git a/src/content/services/kosmeticke-osetreni.json b/src/content/services/kosmeticke-osetreni.json new file mode 100644 index 0000000..0517efe --- /dev/null +++ b/src/content/services/kosmeticke-osetreni.json @@ -0,0 +1,48 @@ +{ + "$schema": "/src/routes/sluzby/schema.json", + "category": "Kosmetické ošetření", + "items": [ + { + "name": "ZÁKLADNÍ CALM", + "description": "Diagnostika pleti, odlíčení tonizace, enzymatický peeling, kavitační peeling -ultarzvuková špachtle, séra dle typu pleti, masky (tvář,krk,dekolt), závěrečná péče (oční a denní krém)", + "id": "zakladni-calm", + "price": 500, + "duration": 1 + }, + { + "name": "ZÁKLADNÍ + CALM PLUS", + "description": "Diagnostika pleti, odlíčení tonizace, úprava obočí (vosk+pinzeta), barvení řas a obočí, depilace horní ret/brada, enzymatický peeling, kavitační peeling -ultarzvuková špachtle, séra dle typu pleti, masky (tvář,krk,dekolt), závěrečná péče (oční a denní krém)", + "id": "zakladni-calm-plus", + "price": 600, + "duration": 1 + }, + { + "name": "RELAXAČNÍ", + "description": "Diagnostika pleti, odlíčení tonizace, úprava obočí (vosk+pinzeta), barvení řas a obočí, depilace horní ret/brada, enzymatický peeling, kavitační peeling -ultarzvuková špachtle, séra, masáž relaxační (tvář,krk dekolt), masky (tvář,krk,dekolt), závěrečná péče (oční a denní krém)", + "id": "relaxacni", + "price": 690, + "duration": 1.5 + }, + { + "name": "LIFTINGOVÉ - ANTI AGE", + "description": "Diagnostika pleti, odlíčení tonizace, úprava obočí (vosk+pinzeta), barvení řas a obočí, depilace horní ret/brada, enzymatický peeling, kavitační peeling -ultarzvuková špachtle, vacupres ošetření – lifting obličeje krku a dekoltu, séra, masky (tvář,krk,dekolt), alginátová maska, závěrečná péče (oční a denní krém)", + "id": "liftingove-anti-age", + "price": 690, + "duration": 1.5 + }, + { + "name": "CLEAR + ANTI AKNÉ", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "clear-anti-akne", + "price": 690, + "duration": 1.5 + }, + { + "name": "Odlíčení + sérum + alginátová maska (PROJASNĚNÍ)", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "odliceni-serum-alginatova-maska", + "price": 300, + "duration": 1 + } + ] +} diff --git a/src/content/services/permanent-mu.json b/src/content/services/permanent-mu.json new file mode 100644 index 0000000..754677f --- /dev/null +++ b/src/content/services/permanent-mu.json @@ -0,0 +1,69 @@ +{ + "$schema": "$routes/sluzby/schema.json", + "category": "Permanentní make-up", + "items": [ + { + "name": "Obočí Pudrové, Ombré", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "oboci", + "price": 3000, + "duration": 2.5 + }, + { + "name": "Horní linky - meziřasové přirozené", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "linky", + "price": 2000, + "duration": 2 + }, + { + "name": "Klasické linky - s ocáskem", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "classic-linky", + "price": 3000, + "duration": 2.5 + }, + { + "name": "Klasické linky - s ocáskem + spodní linky", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "classic-linky+spodni", + "price": 3500, + "duration": 2.5 + }, + { + "name": "Rty - kontura", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "rty", + "price": 2500, + "duration": 2 + }, + { + "name": "3D Rty (kontura a stínování), Full Lips (plné rty)", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "3d-rty", + "price": 3500, + "duration": 2.5 + }, + { + "name": "Aquarelle Lips (přirodní stínování, bez kontury)", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "aquarelle", + "price": 3000, + "duration": 2 + }, + { + "name": "První korekce po aplikaci pmu max. do 3 měsíců", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "korekce", + "price": 1000, + "duration": 1.5 + }, + { + "name": "Oprava práce obočí jiného salonu", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "oprava-oboci", + "price": "na domluvě", + "duration": "na domluvě" + } + ] +} diff --git a/src/content/services/vakuslim.json b/src/content/services/vakuslim.json new file mode 100644 index 0000000..c88dc36 --- /dev/null +++ b/src/content/services/vakuslim.json @@ -0,0 +1,41 @@ +{ + "$schema": "/src/routes/sluzby/schema.json", + "category": "Vakuslim 48 - zeštíhlující procedura", + "items": [ + { + "name": "Ošetření horních končetin", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "vakuslim-48-zestihlujici-procedura-horni-koncetiny", + "price": 600, + "duration": 2 + }, + { + "name": "1 ošetření spodní části těla (břicho, boky, dolní končetiny)", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "vakuslim-48-zestihlujici-procedura-spodni-cast-tela", + "price": 800, + "duration": 2 + }, + { + "name": "1 ošetření komplet horní-dolní části", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "vakuslim-48-zestihlujici-procedura-komplet-horni-dolni-cast", + "price": 1200, + "duration": 2 + }, + { + "name": "6 ošetření předplatné kompet", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "vakuslim-48-zestihlujici-procedura-6-o-setreni-predplatne-kompet", + "price": 6600, + "duration": 2 + }, + { + "name": "12 ošetření předplatné komplet", + "description": "Diagnostika pleti, odlíčení tonizace", + "id": "vakuslim-48-zestihlujici-procedura-12-o-setreni-predplatne-komplet", + "price": 11000, + "duration": 2 + } + ] +} diff --git a/src/routes/sluzby/schema.json b/src/routes/sluzby/schema.json new file mode 100644 index 0000000..c9ca2f1 --- /dev/null +++ b/src/routes/sluzby/schema.json @@ -0,0 +1,74 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Service", + "type": "object", + "required": [ + "category", + "items" + ], + "properties": { + "category": { + "type": "string", + "description": "Name of the category of services", + "minLength": 4, + "default": "Permanentní makeup" + }, + "items": { + "title": "Items under the category", + "type": "array", + "items": { + "type": "object", + "title": "Items", + "properties": { + "name": { + "type": "string", + "description": "Name of the service" + }, + "description": { + "title": "Description", + "type": "string", + "description": "description :D", + "default": "A description of a description" + }, + "id": { + "type": "string", + "description": "a short handle used in urls and on cal.com", + "default": "pmu", + "minLength": 3 + }, + "price": { + "title": "Price", + "description": "Price of the product", + "oneOf": [ + { + "type": "number", + "description": "Price of the service as a number", + "default": 300 + }, + { + "type": "string", + "description": "Price of the service as a text description (e.g., 'Free')", + "default": "na dohode" + } + ] + }, + "duration": { + "title": "Duration", + "description": "How long will the procedure take? (can be on demand or specific amount)", + "oneOf": [ + { + "type": "number", + "description": "Duration of the service in minutes (e.g., 60)", + "minimum": 15 + }, + { + "type": "string", + "description": "Duration of the service as a text description (e.g., 'on demand')" + } + ] + } + } + } + } + } +} diff --git a/tests/ValidateServices.js b/tests/ValidateServices.js new file mode 100644 index 0000000..9c70040 --- /dev/null +++ b/tests/ValidateServices.js @@ -0,0 +1,41 @@ +import Ajv from 'ajv'; +import fs from 'fs'; +import path from 'path'; + +const serviceSchema = JSON.parse(fs.readFileSync('./src/routes/sluzby/schema.json', 'utf-8')); + + +function validateFile(filePath) { + const ajv = new Ajv(); + const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')); + const validate = ajv.compile(serviceSchema); + const valid = validate(data); + if (!valid) { + throw new Error(`Invalid service data in ${filePath}: ${JSON.stringify(validate.errors)}`); + } +} + +function scanDirectory(directory) { + const files = fs.readdirSync(directory); + for (const file of files) { + const filePath = path.join(directory, file); + const stat = fs.statSync(filePath); + if (stat.isDirectory()) { + scanDirectory(filePath); + } else if (path.extname(filePath) === '.json') { + validateFile(filePath); + } + } +} + +export function validateServices() { + try { + scanDirectory('./src/content/services'); + console.log('All services validated successfully!'); + } catch (error) { + console.error(`Error validating services: ${error}`); + process.exit(1); // Exit with non-zero code to signal failure + } +} + +validateServices();