54 Commits

Author SHA1 Message Date
Roland Schneider
16b6107206 [yoga-6] add pricePostfix and price description 2025-05-22 08:12:09 +02:00
Roland Schneider
9dc426bf64 [yoga-4] add article to single service 2025-05-20 16:56:38 +02:00
Roland Schneider
2c71984d96 [yoga-4] add dynamic service page 2025-05-20 16:55:25 +02:00
Roland Schneider
2d4487263d [yoga-0] fix missing upload volume for cms 2025-05-19 10:48:33 +02:00
Roland Schneider
f1daf34751 [yoga-0] fix missing upload volume for cms 2025-05-19 10:42:19 +02:00
e106863c75 [ci-skip] New Prod yoga-app deployment version: 202505180959.57552b3 2025-05-18 19:37:23 +00:00
Jenkins
30128ea7c0 [ci-skip] Update version to 202505180959.57552b3 2025-05-18 12:10:37 +00:00
Jenkins
57552b3cf3 [ci-skip] Update version to 202505180953.5db6974 2025-05-18 09:59:29 +00:00
Jenkins
5db6974d16 [ci-skip] Update version to 202505181151.77363d0 2025-05-18 09:53:08 +00:00
Schneider Roland
77363d0f45 [yoga-3] fix css build issues 2025-05-18 11:51:08 +02:00
Schneider Roland
dbb1bc3073 [yoga-0] improve deployment scripts 2025-05-18 11:14:48 +02:00
7aab555cd2 [ci-skip] New Prod yoga-app deployment version: 202504242104.73ece65 2025-05-18 09:04:30 +00:00
af1ad3227a [ci-skip] New Prod yoga-app deployment version: 202504242104.73ece65 2025-05-18 08:54:35 +00:00
Schneider Roland
07365df5eb [yoga-0] improve deployment scripts 2025-05-18 08:51:38 +02:00
Roland Schneider
8826edfcb6 [yoga-0] add update.service.version.ts 2025-05-17 23:35:26 +02:00
Roland Schneider
c2095b6d8b [yoga-0] add update.service.version.ts 2025-05-17 23:09:09 +02:00
e5bafff815 Merge pull request '[yoga-3] our services carousel' (#8) from feature/yoga-3-services-carousel into main
Reviewed-on: https://gitea.rschneider.hu/rschneider/yogastic/pulls/8
2025-05-17 20:07:25 +00:00
Roland Schneider
f718d553c9 [yoga-3] our services carousel 2025-05-17 22:04:52 +02:00
Schneider Roland
5d6555ea37 [yoga-4] upgrade strapi, add description to yoga achievement 2025-05-13 22:16:36 +02:00
Schneider Roland
cb2b88c53d [yoga-4] upgrade strapi, add description to yoga achievement 2025-05-13 22:11:34 +02:00
Schneider Roland
9036b9ab46 [yoga-4] upgrade strapi, add description to yoga achievement 2025-05-13 22:04:25 +02:00
Roland Schneider
1bb26381d3 [yoga-2] about.us.component.tsx change column sizes 2025-05-06 08:27:18 +02:00
Roland Schneider
001ac9d230 incriease app version to202504252327.477286f 2025-04-25 23:32:04 +02:00
Jenkins
c04be1b56f [ci-skip] Update version to 202504252327.477286f 2025-04-25 21:29:49 +00:00
Roland Schneider
477286fe45 image null check 2025-04-25 23:27:57 +02:00
Roland Schneider
248a80727a update prod deployment 2025-04-25 22:40:31 +02:00
Jenkins
036f194fb1 [ci-skip] Update version to 202504242104.73ece65 2025-04-24 21:17:31 +00:00
Jenkins
73ece6521b [ci-skip] Update version to 202504242303.bbd1ceb 2025-04-24 21:04:32 +00:00
Schneider Roland
bbd1ceb8b5 remove ityped 2025-04-24 23:03:12 +02:00
Schneider Roland
a5fe5c22d1 remove ityped 2025-04-21 22:14:40 +02:00
Schneider Roland
98df36d4e5 fix yoga services 2025-03-28 22:27:53 +01:00
Jenkins
3d0e922326 [ci-skip] Update version to 202503282223.50030fd 2025-03-28 21:24:49 +00:00
Schneider Roland
50030fd72f fix yoga services 2025-03-28 22:23:19 +01:00
Schneider Roland
36a7b8a79b fix yoga services 2025-03-28 22:19:33 +01:00
Schneider Roland
505f5c0840 fix yoga services 2025-03-28 22:17:25 +01:00
Schneider Roland
b9f44caf1a fix yoga services 2025-03-28 22:14:14 +01:00
Schneider Roland
886505885b fix yoga services 2025-03-28 22:09:28 +01:00
Schneider Roland
cf6201cfa9 Update yoga-app image version in Docker Compose configuration 2025-03-09 14:22:23 +01:00
Schneider Roland
bc67a5ae1f Set proxy_shared network to external in Docker Compose configuration 2025-03-08 21:24:27 +01:00
Schneider Roland
fd7e602189 Update version numbers and enhance Docker configurations for improved deployment 2025-03-08 14:18:39 +01:00
Schneider Roland
156658f3fa Update Docker build scripts and production Dockerfile for improved environment configuration 2025-03-08 10:29:31 +01:00
Schneider Roland
0a85108186 fix prod docker cms build 2025-03-08 09:27:02 +01:00
Jenkins
f5a6f527e3 [ci-skip] Update version to 202503062114.abcf521 2025-03-06 21:16:57 +00:00
Jenkins
abcf52111b [ci-skip] Update version to 202503062139.ba93553 2025-03-06 21:14:53 +00:00
Schneider Roland
ba93553b80 fix prod docker variable names 2025-03-06 21:39:37 +01:00
Schneider Roland
6929ed6b03 add scripts to package.json 2025-03-06 21:36:48 +01:00
Schneider Roland
f33ece990d change cms version 2025-03-06 19:09:43 +01:00
Schneider Roland
4375f0dec0 Update Jenkinsfile to change SSH configuration and project directory paths 2025-03-06 19:07:27 +01:00
Jenkins
5ace0a7fd8 [ci-skip] Update version to 202503061710.7df2989 2025-03-06 17:55:49 +00:00
Roland Schneider
7df2989843 improve prod deployment 2025-03-06 17:10:27 +00:00
Schneider Roland
e3b0897727 fix link in nav 2025-03-05 22:40:11 +01:00
Schneider Roland
96b5946eb5 Refactor main header component to use Nav component and update menu labels 2025-03-04 21:14:33 +01:00
Schneider Roland
0cd6f8c0ba Merge remote-tracking branch 'origin/main' 2025-03-04 21:03:24 +01:00
Schneider Roland
bd643a20ca Add encrypted export file for yoga CMS data 2025-03-03 21:50:27 +01:00
52 changed files with 4813 additions and 4290 deletions

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
*.iml
.idea/
/environment/infra/docker-compose/yogastic/.env
/environment/prod/docker-compose/yogastic/.env
node_modules/
.strapi

View File

@@ -22,3 +22,8 @@ x
GET {{domain}}/api/yoga-blog-posts/wmhqy1n8japcfpy0of4hauwm
Accept: application/json
#Authorization: Bearer {{token}}
### GET request with a header
GET {{domain}}/api/yoga-single-services?filters[name][$eq]=service4
Accept: application/json

5
dev.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
cd environment/dev/docker-compose/yogastic
docker compose up -d

1
environment/common/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.env

255
environment/common/package-lock.json generated Normal file
View File

@@ -0,0 +1,255 @@
{
"name": "common",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "common",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@types/js-yaml": "^4.0.9",
"@types/node": "^22.15.18",
"dotenv": "^16.5.0",
"js-yaml": "^4.1.0",
"ts-node": "^10.9.2",
"typescript": "^5.8.3"
}
},
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@tsconfig/node10": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
"license": "MIT"
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"license": "MIT"
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"license": "MIT"
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"license": "MIT"
},
"node_modules/@types/js-yaml": {
"version": "4.0.9",
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
"integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==",
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.15.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz",
"integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/acorn": {
"version": "8.14.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/acorn-walk": {
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
"license": "MIT",
"dependencies": {
"acorn": "^8.11.0"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"license": "MIT"
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"license": "Python-2.0"
},
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"license": "MIT"
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/dotenv": {
"version": "16.5.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz",
"integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"license": "ISC"
},
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"license": "MIT",
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"bin": {
"ts-node": "dist/bin.js",
"ts-node-cwd": "dist/bin-cwd.js",
"ts-node-esm": "dist/bin-esm.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js",
"ts-script": "dist/bin-script-deprecated.js"
},
"peerDependencies": {
"@swc/core": ">=1.2.50",
"@swc/wasm": ">=1.2.50",
"@types/node": "*",
"typescript": ">=2.7"
},
"peerDependenciesMeta": {
"@swc/core": {
"optional": true
},
"@swc/wasm": {
"optional": true
}
}
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"license": "MIT"
},
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"license": "MIT"
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"license": "MIT",
"engines": {
"node": ">=6"
}
}
}
}

View File

@@ -0,0 +1,19 @@
{
"name": "common",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"@types/js-yaml": "^4.0.9",
"@types/node": "^22.15.18",
"dotenv": "^16.5.0",
"js-yaml": "^4.1.0",
"ts-node": "^10.9.2",
"typescript": "^5.8.3"
}
}

View File

@@ -0,0 +1,28 @@
import yaml from 'js-yaml'
import fs from 'fs';
import dotenv from "dotenv"
dotenv.config()
if ( !process.env.TARGET_FILE
|| !process.env.TARGET_SERVICE
|| !process.env.TARGET_IMAGE ) {
console.log("environment variables: TARGET_FILE, TARGET_SERVICE, TARGET_IMAGE are required")
process.exit(1)
}
console.log("Working directory",process.cwd());
console.log("TARGET_FILE",process.env.TARGET_FILE);
console.log("TARGET_SERVICE",process.env.TARGET_SERVICE);
console.log("TARGET_IMAGE",process.env.TARGET_IMAGE);
try {
console.log("updating service version");
const composeFile: any = yaml.load(fs.readFileSync(process.env.TARGET_FILE as string, 'utf8'));
console.log("updating image");
composeFile.services[process.env.TARGET_SERVICE as string].image = process.env.TARGET_IMAGE;
const result = yaml.dump(composeFile);
fs.writeFileSync(process.env.TARGET_FILE as string, result)
console.log("image updated",process.env.TARGET_FILE,process.env.TARGET_SERVICE,process.env.TARGET_IMAGE);
} catch (e) {
console.log(e);
}

View File

@@ -0,0 +1,113 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "libReplacement": true, /* Enable lib replacement. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
// "noUncheckedSideEffectImports": true, /* Check side effect imports. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}

View File

@@ -1 +1 @@
202502252004.fad4103
202505181151.77363d0

View File

@@ -9,4 +9,4 @@ echo "build image ${TAG} from folder ${PROJECT_ROOT}"
cd $PROJECT_ROOT
docker build -t $TAG .
docker build --build-arg NODE_ENV=production -t $TAG .

View File

@@ -1 +1 @@
202502251913.4385f28
202505180959.57552b3

View File

@@ -65,7 +65,7 @@ services:
SITE_MAIL_RECIEVER: ${APP_SITE_MAIL_RECIEVER}
cms:
image: docker.rschneider.hu/infra/yoga-cms:202502251913.4385f28
image: docker.rschneider.hu/infra/yoga-cms:202503282223.50030fd
ports:
- "4024:1337"
environment:

View File

@@ -1,5 +1,4 @@
services:
strapi-db:
image: mariadb:11.6.2
environment:
@@ -9,21 +8,23 @@ services:
MARIADB_PASSWORD: strapi
volumes:
- strapi-db:/var/lib/mysql
networks:
- yogastic
nextjs-db:
image: postgres:17
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DATABASE}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${APP_POSTGRES_PASSWORD}
POSTGRES_DB: ${APP_POSTGRES_DATABASE}
POSTGRES_USER: ${APP_POSTGRES_USER}
volumes:
- next-db:/var/lib/postgresql/data
networks:
- yogastic
app:
image: docker.rschneider.hu/infra/yoga-app:202502252004.fad4103
image: docker.rschneider.hu/infra/yoga-app:202505181151.77363d0
platform: linux/amd64
ports:
- "4025:3000"
- '4025:3000'
environment:
POSTGRES_URL: ${APP_POSTGRES_URL}
POSTGRES_URL_NON_POOLING: ${APP_POSTGRES_URL_NON_POOLING}
@@ -42,11 +43,13 @@ services:
SMTP_SERVER_PORT: ${APP_SMTP_SERVER_PORT}
SMTP_SERVER_SECURE: ${APP_SMTP_SERVER_SECURE}
SITE_MAIL_RECIEVER: ${APP_SITE_MAIL_RECIEVER}
networks:
- proxy_shared
- yogastic
cms:
image: docker.rschneider.hu/infra/yoga-cms:202502251913.4385f28
image: docker.rschneider.hu/infra/yoga-cms:202505180959.57552b3
ports:
- "4026:1337"
- '4026:1337'
environment:
DATABASE_CLIENT: mysql
DATABASE_HOST: strapi-db
@@ -56,12 +59,24 @@ services:
DATABASE_PASSWORD: strapi
HOST: 0.0.0.0
PORT: 1337
APP_KEYS: "yoga1,yoga2"
APP_KEYS: yoga1,yoga2
API_TOKEN_SALT: diana
ADMIN_JWT_SECRET: 6d49a635a298dfff1457002ab1ea26d51f94f6c67c03f7299e8adc19aafe02a2aadb2258aa1be90b836898e0b1ce6970d7584dda32129fb0e4aa09db9ba2076909a44491bbf1c0e1840b8a78843388851ed80407a71fabc3674faca3b4c4fd147c86347a390e86051b1530cac454063bb351632c75852110a5dc198f96a4f4b709d34d240d3e82206f29756a703d7b873b387d7a20e87df71f31a2f934d2a32a3795898c8d43d7f088ebfc8c430b81f4112b811c2aac6be8af551afd8cc29c4875037fd5c7fdacfcd5740b89bab0e1ada51b23f99fb0d181a8ad4758447331edd339ce988e02a6eae170ff57b6650f91dfb2988f7d91be6ea330c0e8fd647799
ADMIN_JWT_SECRET: >-
6d49a635a298dfff1457002ab1ea26d51f94f6c67c03f7299e8adc19aafe02a2aadb2258aa1be90b836898e0b1ce6970d7584dda32129fb0e4aa09db9ba2076909a44491bbf1c0e1840b8a78843388851ed80407a71fabc3674faca3b4c4fd147c86347a390e86051b1530cac454063bb351632c75852110a5dc198f96a4f4b709d34d240d3e82206f29756a703d7b873b387d7a20e87df71f31a2f934d2a32a3795898c8d43d7f088ebfc8c430b81f4112b811c2aac6be8af551afd8cc29c4875037fd5c7fdacfcd5740b89bab0e1ada51b23f99fb0d181a8ad4758447331edd339ce988e02a6eae170ff57b6650f91dfb2988f7d91be6ea330c0e8fd647799
TRANSFER_TOKEN_SALT: 2209851913
JWT_SECRET: fc2be7f56eefe9790bd80a3713974620f42a66313f71bb581ac15328b886ccd42c51eb54f6e897b5d3f6d12bec069dfd116eb63f09d709346ab8c5c328ff42cef1f1cd7e39448186c9c96af3d838e25a3e82dfe72578d775f322bfb3b280ee7db103ae768dcebfc3fa0a9fffeb4d4773cd70e818f6cd8e98f360faa926a8388d18a1c9abcb616600c2c450820a29328df5592dea4a76edf3e9f8147cf92fc88a8a9e3f3698e038c9f7ccbfd7fc04fada3583f2ad8d1ff087a6f23cd33cfc8edf82e6489f1470da5dc52bc1ab1ac025bc9f77a6098f5efecff451498e2d936d005284e149971df15ed81d92ddddd0f71b5ffa3584d853aa3cecc37652430e7d27
JWT_SECRET: >-
fc2be7f56eefe9790bd80a3713974620f42a66313f71bb581ac15328b886ccd42c51eb54f6e897b5d3f6d12bec069dfd116eb63f09d709346ab8c5c328ff42cef1f1cd7e39448186c9c96af3d838e25a3e82dfe72578d775f322bfb3b280ee7db103ae768dcebfc3fa0a9fffeb4d4773cd70e818f6cd8e98f360faa926a8388d18a1c9abcb616600c2c450820a29328df5592dea4a76edf3e9f8147cf92fc88a8a9e3f3698e038c9f7ccbfd7fc04fada3583f2ad8d1ff087a6f23cd33cfc8edf82e6489f1470da5dc52bc1ab1ac025bc9f77a6098f5efecff451498e2d936d005284e149971df15ed81d92ddddd0f71b5ffa3584d853aa3cecc37652430e7d27
networks:
- proxy_shared
- yogastic
volumes:
- strapi-uploads:/opt/app/public/uploads
volumes:
next-db: {}
strapi-db: {}
strapi-uploads: {}
networks:
yogastic: null
proxy_shared:
external: true

View File

@@ -4,12 +4,14 @@ pipeline {
stages {
stage('Git pull && docker compose restart') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'rschneider', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''
cd /home/rschneider/projects/yogastic
sshPublisher(publishers: [sshPublisherDesc(configName: 'rschneider.hu', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''
cd /home/rocho/projects/yogastic
git pull
cd /home/rschneider/projects/yogastic/environment/prod/docker-compose/yogastic
cd /home/rocho/projects/yogastic/environment/prod/docker-compose/yogastic
docker compose down
docker compose up -d
cd /home/rocho/docker/proxy/proxy
bash ./restart.sh
''', execTimeout: 120000,
flatten: false,
makeEmptyDirs: false,

View File

@@ -0,0 +1,221 @@
pipeline {
agent any
environment {
DOCKER_CREDS = 'rschneider@docker.rschneider.hu'
GIT_USER = "Roland Schneider"
GIT_EMAIL = "rocho02@gmail.com"
GIT_REPO = "gitea.rschneider.hu/rschneider/yogastic.git"
GIT_BRANCH = "main"
GIT_CREDS_ID = "rschneider_gitea.rschneider.hu"
CMS_IMAGE= "docker.rschneider.hu/infra/yoga-cms"
APP_IMAGE= "docker.rschneider.hu/infra/yoga-app"
}
stages {
stage('Checkout') {
steps {
git branch: 'main', credentialsId: "${GIT_CREDS_ID}", url: "https://${GIT_REPO}"
sh '''
ls -lah
'''
}
}
stage('Collect project info - cms') {
agent{
docker {
reuseNode true
image 'linuxserver/yq'
}
}
steps {
withCredentials([usernamePassword(credentialsId: "${GIT_CREDS_ID}", passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME')]) {
script {
def block = ""
block = sh returnStdout:true, script:'''
yq -y '.services.cms.image' environment/prod/docker-compose/yogastic/docker-compose.yaml
'''
block = block.readLines();
env.CMS_CURRENT = block[0];
block = sh returnStdout:true, script:'''
cat environment/dev/docker/cms/scripts/version.txt
'''
block = block.readLines();
env.CMS_LATEST = block[0];
def apiUrl = "https://docker.rschneider.hu/v2/infra/yoga-cms/tags/list"
def tagsResponse = sh(script: """
curl -s -u "${DOCKER_USERNAME}:${DOCKER_PASSWORD}" ${apiUrl}
""", returnStdout: true).trim()
// Step 3: Use JsonSlurper to parse the JSON response
def jsonSlurper = new groovy.json.JsonSlurper()
def tags = jsonSlurper.parseText(tagsResponse)
// Extract the tag names
def availableTags = tags.tags.collect { it }
availableTags = availableTags.reverse()
println availableTags
env.CMS_TAGS = availableTags.join("\n")
}
}
}
}
stage('Collect project info - app') {
agent{
docker {
reuseNode true
image 'linuxserver/yq'
}
}
steps {
withCredentials([usernamePassword(credentialsId: 'rschneider@docker.rschneider.hu', passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME')]) {
script {
def block = ""
block = sh returnStdout:true, script:'''
yq -y '.services.app.image' environment/prod/docker-compose/yogastic/docker-compose.yaml
'''
block = block.readLines();
env.APP_CURRENT = block[0];
block = sh returnStdout:true, script:'''
cat environment/dev/docker/app/scripts/version.txt
'''
block = block.readLines();
env.APP_LATEST = block[0];
def apiUrl = "https://docker.rschneider.hu/v2/infra/yoga-app/tags/list"
def tagsResponse = sh(script: """
curl -s -u "${DOCKER_USERNAME}:${DOCKER_PASSWORD}" ${apiUrl}
""", returnStdout: true).trim()
// Step 3: Use JsonSlurper to parse the JSON response
def jsonSlurper = new groovy.json.JsonSlurper()
def tags = jsonSlurper.parseText(tagsResponse)
// Extract the tag names
def availableTags = tags.tags.collect { it }
availableTags = availableTags.reverse()
env.APP_TAGS = availableTags.join("\n")
}
}
}
}
stage('Select version CMS') {
steps {
echo "new tags"
println env.CMS_TAGS
script{
env.CMS_VERSION = input message: 'Select version for PROD', ok: 'Update',
parameters: [choice(name: 'Select version', choices: env.CMS_TAGS, description: """
Latest: ${env.CMS_LATEST}
Current: ${env.CMS_CURRENT}
""" )]
echo "You have selected Docker Tag: ${env.CMS_VERSION}"
}
}
}
stage('Select version APP') {
steps {
echo "new APP tags"
println env.APP_TAGS
script{
env.APP_VERSION = input message: 'Select version for PROD', ok: 'Update',
parameters: [choice(name: 'Select version', choices: env.APP_TAGS, description: """
Latest: ${env.APP_LATEST}
Current: ${env.APP_CURRENT}
""")]
echo "You have selected Docker Tag: ${env.APP_VERSION}"
}
}
}
stage('Update version CMS') {
agent{
docker {
reuseNode true
image 'node:22'
}
}
steps {
script{
env.TARGET_FILE='../prod/docker-compose/yogastic/docker-compose.yaml'
env.TARGET_SERVICE='cms'
env.TARGET_IMAGE= "${CMS_IMAGE}:${CMS_VERSION}"
sh '''
cd environment/common
npm i -c
npx ts-node src/update.service.version.ts
'''
}
}
}
stage('Update version APP') {
agent{
docker {
reuseNode true
image 'node:22'
}
}
steps {
script{
env.TARGET_FILE='../prod/docker-compose/yogastic/docker-compose.yaml'
env.TARGET_SERVICE='app'
env.TARGET_IMAGE= "${APP_IMAGE}:${APP_VERSION}"
sh '''
cd environment/common
npm i -c
npx ts-node src/update.service.version.ts
'''
}
}
}
stage('Update git ') {
/*
agent{
docker {
reuseNode true
image 'alpine/git'
args '--entrypoint /bin/sh'
}
}
*/
environment{
GIT_CREDS = credentials("${GIT_CREDS_ID}")
ENV_NAME = "Prod yoga-app"
IMAGE_VERSION = "${CMS_VERSION}"
}
steps {
sh '''
git status
git config user.email "${GIT_EMAIL}"
git config user.name "${GIT_USER}"
git commit -a -m "[ci-skip] New ${ENV_NAME} deployment version: ${IMAGE_VERSION}"
git push --tags https://$GIT_CREDS@$GIT_REPO $GIT_BRANCH
'''
}
}
}
}

View File

@@ -6,8 +6,9 @@
"test": "echo \"Error: no test specified\" && exit 1",
"build.docker.image.yogastic": "cd environment/dev/docker/yogastic/scripts && bash build.docker.build.sh",
"build.docker.image.app": "cd environment/dev/docker/app/scripts && bash build.docker.build.sh ",
"build.docker.image.cms": "cd environment/dev/docker/cms/scripts && bash build.docker.build.sh "
"build.docker.image.cms": "cd environment/dev/docker/cms/scripts && bash build.docker.build.sh ",
"push.docker.image.app": "cd environment/dev/docker/app/scripts && bash build.docker.push.sh ",
"push.docker.image.cms": "cd environment/dev/docker/cms/scripts && bash build.docker.push.sh "
},
"author": "",
"license": "ISC",

View File

@@ -2,7 +2,7 @@ import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __filename = fileURLToPath(import.meta?.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({

View File

@@ -17,6 +17,7 @@
"@types/ityped": "^1.0.3",
"@types/pg": "^8.11.10",
"@types/qs": "^6.9.18",
"@types/react-slick": "^0.23.13",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"ajv-i18n": "^4.2.0",
@@ -33,12 +34,14 @@
"react": "^19.0.0",
"react-bootstrap": "^2.10.9",
"react-dom": "^19.0.0",
"react-slick": "^0.30.3",
"slick-carousel": "^1.8.1",
"validator": "^13.12.0"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@types/bcryptjs": "^2.4.6",
"@types/node": "^20",
"@types/node": "^20.17.47",
"@types/nodemailer": "^6.4.17",
"@types/react": "^19",
"@types/react-dom": "^19",
@@ -1567,9 +1570,10 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "20.17.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.10.tgz",
"integrity": "sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==",
"version": "20.17.47",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.47.tgz",
"integrity": "sha512-3dLX0Upo1v7RvUimvxLeXqwrfyKxUINk0EAM83swP2mlSUcwV73sZy8XhNz8bcZ3VbsfQyC/y6jRdL5tgCNpDQ==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.19.2"
}
@@ -1673,6 +1677,15 @@
"@types/react": "^19.0.0"
}
},
"node_modules/@types/react-slick": {
"version": "0.23.13",
"resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.13.tgz",
"integrity": "sha512-bNZfDhe/L8t5OQzIyhrRhBr/61pfBcWaYJoq6UDqFtv5LMwfg4NsVDD2J8N01JqdAdxLjOt66OZEp6PX+dGs/A==",
"license": "MIT",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/react-transition-group": {
"version": "4.4.12",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
@@ -2739,6 +2752,12 @@
"node": ">=10.13.0"
}
},
"node_modules/enquire.js": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz",
"integrity": "sha512-/KujNpO+PT63F7Hlpu4h3pE3TokKRHN26JYmQpPyjkRD/N57R7bPDNojMXdi7uveAKjYB7yQnartCxZnFWr0Xw==",
"license": "MIT"
},
"node_modules/es-abstract": {
"version": "1.23.8",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.8.tgz",
@@ -4383,6 +4402,7 @@
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
@@ -4407,6 +4427,15 @@
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true
},
"node_modules/json2mq": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz",
"integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==",
"license": "MIT",
"dependencies": {
"string-convert": "^0.2.0"
}
},
"node_modules/json5": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
@@ -5550,6 +5579,23 @@
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"node_modules/react-slick": {
"version": "0.30.3",
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.30.3.tgz",
"integrity": "sha512-B4x0L9GhkEWUMApeHxr/Ezp2NncpGc+5174R02j+zFiWuYboaq98vmxwlpafZfMjZic1bjdIqqmwLDcQY0QaFA==",
"license": "MIT",
"dependencies": {
"classnames": "^2.2.5",
"enquire.js": "^2.1.6",
"json2mq": "^0.2.0",
"lodash.debounce": "^4.0.8",
"resize-observer-polyfill": "^1.5.0"
},
"peerDependencies": {
"react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@@ -5644,6 +5690,12 @@
"node": ">=0.10.0"
}
},
"node_modules/resize-observer-polyfill": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==",
"license": "MIT"
},
"node_modules/resolve": {
"version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
@@ -5981,6 +6033,15 @@
"is-arrayish": "^0.3.1"
}
},
"node_modules/slick-carousel": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/slick-carousel/-/slick-carousel-1.8.1.tgz",
"integrity": "sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==",
"license": "MIT",
"peerDependencies": {
"jquery": ">=1.8.0"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -6035,6 +6096,12 @@
"node": ">=0.6.19"
}
},
"node_modules/string-convert": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz",
"integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==",
"license": "MIT"
},
"node_modules/string.prototype.includes": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",

View File

@@ -19,6 +19,7 @@
"@types/ityped": "^1.0.3",
"@types/pg": "^8.11.10",
"@types/qs": "^6.9.18",
"@types/react-slick": "^0.23.13",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"ajv-i18n": "^4.2.0",
@@ -35,12 +36,14 @@
"react": "^19.0.0",
"react-bootstrap": "^2.10.9",
"react-dom": "^19.0.0",
"react-slick": "^0.30.3",
"slick-carousel": "^1.8.1",
"validator": "^13.12.0"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@types/bcryptjs": "^2.4.6",
"@types/node": "^20",
"@types/node": "^20.17.47",
"@types/nodemailer": "^6.4.17",
"@types/react": "^19",
"@types/react-dom": "^19",

View File

@@ -13,6 +13,7 @@ import {ServicesPage_Plain} from "@/types/generated-strapi-interfaces/api/servic
import {PricesPage_Plain} from "@/types/generated-strapi-interfaces/api/prices-page";
import {FaqPage_Plain} from "@/types/generated-strapi-interfaces/api/faq-page";
import {ContactPage_Plain} from "@/types/generated-strapi-interfaces/api/contact-page";
import {YogaSingleService_Plain} from "@/types/generated-strapi-interfaces/api/yoga-single-service";
class StrapiApi{
@@ -42,6 +43,16 @@ class StrapiApi{
return this.getJson("/api/services-page?",servicesQuery);
}
public getServicePage(name: string): Promise<YogaSingleService_Plain[]>{
return this.getJson("/api/yoga-single-services?", {
filters: {
name: {
$eq: name,
},
},
});
}
public getPricesPage(): Promise<PricesPage_Plain>{
return this.getJson("/api/prices-page?",pricesQuery);
}

View File

@@ -8,6 +8,9 @@ class StrapiClient{
constructor(private strapiUrl: string = "http://localhost:1337") {
}
public getImageUrl(imagePath: string){
if ( !imagePath ){
return "dummy.png"
}
return '/image/'+ imagePath;
}
public async httpGet(path: string){

View File

@@ -11,7 +11,6 @@ import FooterComponent from "@/components/footer.component";
import SubscribeComponent from "@/components/subscribe.component";
import MainHeaderComponent from "@/components/mainHeaderComponent";
import BootstrapComponent from "@/components/bootstrap.component";
import ITypedComponent from "@/components/ityped.component";
import webApi from "@/api/web-client/web-api";
export default async function Home() {
@@ -34,8 +33,8 @@ export default async function Home() {
return (
<>
{ header && <MainHeaderComponent config={header}/> }
{ ourServices && <OurServicesComponent header={ourServices.header!} description={ourServices.description!} title={ourServices.title!}/> }
{ aboutUs && <AboutUsComponent data={aboutUs} /> }
{ ourServices && <OurServicesComponent config={ourServices}/> }
{ ourSpecialities && <OurSpecialitiesComponent config={ourSpecialities} /> }
{ contactUs && <ContactUsComponent contactUs={contactUs} /> }
{ prices && <PricingComponent config={prices}/> }
@@ -45,7 +44,6 @@ export default async function Home() {
{ footer && <FooterComponent config={footer} /> }
<AosComponent />
<BootstrapComponent />
{header?.headerIType && <ITypedComponent text={header.headerIType} /> }
</>
);

View File

@@ -0,0 +1,27 @@
import React from "react";
import strapiApi from "@/api/strapi/strapi-api";
export default async function ServiceArticlePage({params}: {
params: { slug: string}
} ) {
const servicesByName = await strapiApi.getServicePage(params.slug);
// return (
// <>
// {header && description && <SubHeaderComponent header1={header} description={description} />}
// { ourServices && <OurServicesComponent config={ourServices} /> }
// { contactUs && <ContactUsComponent contactUs={contactUs} />}
// { ourSpecialities && <OurSpecialitiesComponent config={ourSpecialities} /> }
// { feedbacks && <FeedbackComponent config={feedbacks} /> }
// { blogs && <BlogPostsComponent config={blogs} /> }
// { subscribe && <SubscribeComponent config={subscribe} /> }
// { footer && <FooterComponent config={footer} /> }
// <AosComponent />
// </>
// );
console.info("slug", params.slug);
console.info("servicesByName", servicesByName);
return (
<div>hello world {params.slug}</div>
);
}
export const dynamic = 'force-dynamic'

View File

@@ -25,7 +25,7 @@ export default async function Services() {
return (
<>
{header && description && <SubHeaderComponent header1={header} description={description} />}
{ ourServices && <OurServicesComponent header={ourServices.header!} title={ourServices.title!} description={ourServices.description!} /> }
{ ourServices && <OurServicesComponent config={ourServices} /> }
{ contactUs && <ContactUsComponent contactUs={contactUs} />}
{ ourSpecialities && <OurSpecialitiesComponent config={ourSpecialities} /> }
{ feedbacks && <FeedbackComponent config={feedbacks} /> }

View File

@@ -14,9 +14,9 @@ const AboutUsComponent = ( {data: {title,header,description,content,buttonText,b
<section className="aboutus_section">
<div className="container">
<div className="row">
<div className="col-lg-7 col-md-7 col-sm-12 col-xs-12">
<div className="col-lg-5 col-md-5 col-sm-12 col-xs-12">
<div className="aboutus_image">
<figure className="mb-0"><YogaImageComponent src={strapiApi.getImageUrl(fileImage.url)} alt="" className="img-fluid"/></figure>
<figure className="mb-0"><YogaImageComponent src={strapiApi.getImageUrl(fileImage?.url)} alt="" className="img-fluid"/></figure>
</div>
<figure className="aboutus_top_shape left_shape mb-0">
<YogaImageComponent src="/assets/images/aboutus_top_shape.png" alt="" className="img-fluid"/>
@@ -25,7 +25,7 @@ const AboutUsComponent = ( {data: {title,header,description,content,buttonText,b
<YogaImageComponent src="/assets/images/aboutus_bottom_shape.png" alt="" className="img-fluid"/>
</figure>
</div>
<div className="col-lg-5 col-md-5 col-sm-12 col-xs-12" data-aos="fade-right">
<div className="col-lg-7 col-md-7 col-sm-12 col-xs-12" data-aos="fade-right">
<div className="aboutus_content">
<h5>{title}</h5>
<h2>{header}</h2>

View File

@@ -8,7 +8,7 @@ export interface Props{
}
export default function AchievementsItemComponent({achievement
:{ image}
:{ image,description}
}: Props){
const imageFile: StrapiFile = image as StrapiFile;
@@ -16,6 +16,9 @@ const imageFile: StrapiFile = image as StrapiFile;
<div className="col-lg-2 col-md-4 col-sm-6 col-xs-12">
<div className="logo_wrapper">
<figure className="mb-0"><YogaImageComponent src={strapiApi.getImageUrl(imageFile?.url)} alt="" className="img-fluid"/></figure>
<div className="logo_content">
{description}
</div>
</div>
</div>

View File

@@ -14,7 +14,7 @@ const BlogSinglePostComponent = ({post: {header,teaserImage,tags,documentId} }:
<div className="col-lg-6 col-md-6 col-sm-12 col-xs-12">
<div className="blog_posts_image position-relative">
<figure className="mb-0">
<YogaImageComponent src={strapiApi.getImageUrl( teaserFile.url ) } alt=""
<YogaImageComponent src={strapiApi.getImageUrl( teaserFile?.url ) } alt=""
className="img-fluid"/>
</figure>
<div className="blog_posts_image_content">

View File

@@ -16,7 +16,7 @@ const FeedbackComponent = ({active,config: {customerName, feedback, customerImag
<div className="testimonial_content">
<i className="fa-solid fa-quote-left"></i>
<p className="testimonial_paragraph">{feedback}</p>
<figure><YogaImageComponent src={strapiApi.getImageUrl(imageFile.url)} alt=""
<figure><YogaImageComponent src={strapiApi.getImageUrl(imageFile?.url)} alt=""
className="img-fluid"/></figure>
<p className="testimonial_person_name">{customerName}</p>
<span>{customerDescription}</span>

View File

@@ -1,5 +1,7 @@
import YogaImageComponent from "@/components/yoga.image.component";
import {YogaMainHeaderComponent_Plain} from "@/types/generated-strapi-interfaces/api/yoga-main-header-component";
import {MAIN_MENU} from "@/util/const";
import Nav from "@/components/nav.component";
export interface Props{
config: YogaMainHeaderComponent_Plain
}
@@ -8,92 +10,14 @@ const MainHeaderComponent = ({ config: {
header,
description,
button,
headerIType
}}: Props) => {
return (
<div className="banner-section-outer">
<header>
<div className="main_header">
<div className="container-fluid">
<nav className="navbar navbar-expand-lg navbar-light p-0">
<a className="navbar-brand" href="/index"><figure className="mb-0"><YogaImageComponent src="/assets/images/yogastic_logo.png" alt=""/></figure></a>
<button className="navbar-toggler collapsed" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
<span className="navbar-toggler-icon"></span>
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav">
<li className="nav-item active">
<a className="nav-link" href="/index">Home</a>
</li>
<li className="nav-item">
<a className="nav-link" href="/about">About Us</a>
</li>
<li className="nav-item">
<a className="nav-link" href="/services">Services</a>
</li>
<li className="nav-item dropdown">
<a className="nav-link dropdown-toggle dropdown-color navbar-text-color" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false"> Pages </a>
<div className="dropdown-menu drop-down-content">
<ul className="list-unstyled drop-down-pages">
<li className="nav-item">
<a className="dropdown-item nav-link" href="/pricing">Pricing</a>
</li>
<li className="nav-item">
<a className="dropdown-item nav-link" href="/faq">Faq</a>
</li>
</ul>
</div>
</li>
<li className="nav-item">
<a className="nav-link" href="/team">Team</a>
</li>
<li className="nav-item dropdown">
<a className="nav-link dropdown-toggle dropdown-color navbar-text-color" href="#" id="navbarDropdown2" role="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false"> Blog </a>
<div className="dropdown-menu drop-down-content">
<ul className="list-unstyled drop-down-pages">
<li className="nav-item">
<a className="dropdown-item nav-link" href="/single-post">Single Post</a>
</li>
<li className="nav-item">
<a className="dropdown-item nav-link" href="/infinite-scroll">Infinite Scroll</a>
</li>
<li className="nav-item">
<a className="dropdown-item nav-link" href="/load-more">Load More</a>
</li>
<li className="nav-item">
<a className="dropdown-item nav-link" href="/one-column">One Column</a>
</li>
<li className="nav-item">
<a className="dropdown-item nav-link" href="/two-column">Two Column</a>
</li>
<li className="nav-item">
<a className="dropdown-item nav-link" href="/three-column">Three Column</a>
</li>
<li className="nav-item">
<a className="dropdown-item nav-link" href="/three-colum-sidbar">Three Column Sidebar</a>
</li>
<li className="nav-item">
<a className="dropdown-item nav-link" href="/four-column">Four Column</a>
</li>
<li className="nav-item">
<a className="dropdown-item nav-link" href="/six-column">Six Column</a>
</li>
</ul>
</div>
</li>
<li className="nav-item">
<a className="nav-link contact_us" href="/contact">Contact Us</a>
</li>
</ul>
</div>
</nav>
</div>
</div>
<Nav menuItems={MAIN_MENU} />
</header>
{/*<!-- SOCIAL ICONS -->*/}
<div className="social-icons left_icons float-left d-table" data-aos="fade-down">
@@ -117,7 +41,7 @@ const MainHeaderComponent = ({ config: {
<div className="col-lg-6 col-md-6 col-sm-12 col-xs-12 text-md-left text-center">
<div className="banner-section-content">
<h5>{title}</h5>
<h1 data-aos="fade-up">{header} <span className="ityped"></span></h1>
<h1 data-aos="fade-up">{header} <span className="{}">{headerIType}</span></h1>
<p data-aos="fade-right">{description}</p>
<div className="btn_wrapper" data-aos="fade-up">
{button && <a className="text-decoration-none getstarted_btn" href={button.link}>{button.label}</a> }

View File

@@ -2,6 +2,7 @@
import {FC} from "react";
import YogaImageComponent from "@/components/yoga.image.component";
import clsx from "clsx";
import Link from "next/link";
export interface MenuItem{
href?: string;
@@ -23,10 +24,10 @@ const Nav: FC<Props> = ({menuItems}:Props) => {
<div className="main_header">
<div className="container-fluid">
<nav className="navbar navbar-expand-lg navbar-light p-0">
<a className="navbar-brand" href="/index">
<Link className="navbar-brand" href="/">
<figure className="mb-0"><YogaImageComponent src="/assets/images/yogastic_logo.png" alt=""/>
</figure>
</a>
</Link>
<button className="navbar-toggler collapsed" type="button" data-toggle="collapse"
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">

View File

@@ -1,11 +1,73 @@
'use client';
import YogaImageComponent from "@/components/yoga.image.component";
import {YogaOurServicesComponent_Plain} from "@/types/generated-strapi-interfaces/api/yoga-our-services-component";
// import OurServiceItemComponent from "@/components/our.services.item.component";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import Slider ,{Settings} from "react-slick";
import OurServiceItemComponent from "@/components/our.services.item.component";
export interface Props{
title: string;
header: string;
description: string;
config: YogaOurServicesComponent_Plain
}
const OurServiceComponent = ({title,header,description}: Props) => {
const OurServiceComponent = ({config: {title,header,description,services}}: Props) => {
const settings: Settings = {
dots: true,
infinite: true,
speed: 500,
slidesToShow: 4,
slidesToScroll: 1,
swipe: true,
responsive: [
/**
*
* col-lg-3 col-md-6 col-sm-6 col-xs-12
*
* Breakpoint Class infix Dimensions
* X-Small None <576px
* Small sm ≥576px
* Medium md ≥768px
* Large lg ≥992px
* Extra large xl ≥1200px
* Extra extra large xxl ≥1400px
*/
{
breakpoint: 992,
settings: {
slidesToShow: 4,
slidesToScroll: 1,
infinite: true,
dots: true
}
},
{
breakpoint: 768,
settings: {
slidesToShow: 2,
slidesToScroll: 1,
initialSlide: 1
}
},
{
breakpoint: 576,
settings: {
slidesToShow: 2,
slidesToScroll: 1,
initialSlide: 1
}
},
{
breakpoint: 480,
settings: {
slidesToShow: 1,
slidesToScroll: 1
}
}
]
};
console.info(settings)
return (
<section className="services_section">
<div className="container">
@@ -18,72 +80,21 @@ const OurServiceComponent = ({title,header,description}: Props) => {
</div>
</div>
</div>
<div className="row" data-aos="fade-up">
<div className="col-lg-3 col-md-6 col-sm-6 col-xs-12">
<div className="services_box_content">
<div className="services_box_upper_portion">
<figure className="mb-0"><YogaImageComponent src="/assets/images/services_img_1.png" alt=""
className="img-fluid"/></figure>
</div>
<div className="services_box_lower_portion">
<h3>Prenatal Yoga</h3>
<p>Finibus metus elit tempus faucibus urna nunc aui.</p>
<div className="btn_wrapper">
<a href="/services" className="text-decoration-none"><i
className="fa-solid fa-arrow-right" aria-hidden="true"></i></a>
</div>
</div>
</div>
</div>
<div className="col-lg-3 col-md-6 col-sm-6 col-xs-12">
<div className="services_box_content">
<div className="services_box_upper_portion">
<figure className="mb-0"><YogaImageComponent src="/assets/images/services_img_2.png" alt=""
className="img-fluid"/></figure>
</div>
<div className="services_box_lower_portion">
<h3>Meditation</h3>
<p>Ainibus metus elit tempus faucibus urna nunc cui.</p>
<div className="btn_wrapper">
<a href="/services" className="text-decoration-none"><i
className="fa-solid fa-arrow-right" aria-hidden="true"></i></a>
</div>
</div>
</div>
</div>
<div className="col-lg-3 col-md-6 col-sm-6 col-xs-12">
<div className="services_box_content">
<div className="services_box_upper_portion">
<figure className="mb-0"><YogaImageComponent src="/assets/images/services_img_3.png" alt=""
className="img-fluid"/></figure>
</div>
<div className="services_box_lower_portion">
<h3>Nutrition Consultation</h3>
<p>Binibus metus elit tempus faucibus urna nunc eui.</p>
<div className="btn_wrapper">
<a href="/services" className="text-decoration-none"><i
className="fa-solid fa-arrow-right" aria-hidden="true"></i></a>
</div>
</div>
</div>
</div>
<div className="col-lg-3 col-md-6 col-sm-6 col-xs-12">
<div className="services_box_content">
<div className="services_box_upper_portion">
<figure className="mb-0"><YogaImageComponent src="/assets/images/services_img_4.png" alt=""
className="img-fluid"/></figure>
</div>
<div className="services_box_lower_portion">
<h3>Hatha Yoga</h3>
<p>Dinibus metus elit tempus faucibus urna nunc rui.</p>
<div className="btn_wrapper">
<a href="/services" className="text-decoration-none"><i
className="fa-solid fa-arrow-right" aria-hidden="true"></i></a>
</div>
</div>
</div>
</div>
</div>
{/*<div className="row" data-aos="fade-up">*/}
{/* {services.map(*/}
{/* itemConfig =>*/}
{/* <OurServiceItemComponent config={itemConfig} key={itemConfig.id} />*/}
{/* )}*/}
{/*</div>*/}
<Slider {...settings}>
{services.map(
itemConfig =>
<OurServiceItemComponent config={itemConfig} key={itemConfig.id} />
)}
</Slider>
<figure className="services_left_shape left_shape mb-0">
<YogaImageComponent src="/assets/images/services_left_shape.png" alt="" className="img-fluid"/>
</figure>

View File

@@ -0,0 +1,37 @@
/*.serviceSlide{*/
/*}*/
/*button.slick-arrow:first-of-type{*/
/* left: 6px;*/
/* z-index: 1;*/
/*}*/
/*button.slick-arrow:last-of-type{*/
/* right: 6px;*/
/*}*/
.serviceSlide{
margin: 0 6px;
}
.slick-track :global(.slick-active){
padding-left: 3px;
padding-right: 3px;
}
.slick-track :global(div:nth-child(1 of .slick-active)){
padding-left: 0;
padding-right: 3px;
}
.slick-track :global(div:nth-last-child(1 of .slick-active)){
padding-left: 3px;
padding-right: 0;
}
/*:global(div.slick-active):nth-last-child(n!*){*/
/* padding-left: 6px;*/
/* padding-right: 0;*!*/
/*}*/

View File

@@ -0,0 +1,37 @@
import YogaImageComponent from "@/components/yoga.image.component";
import {YogaSingleService_Plain} from "@/types/generated-strapi-interfaces/api/yoga-single-service";
import {StrapiFile} from "@/types/types";
import strapiApi from "@/api/strapi/strapi-api";
import styles from './our.services.item.component.module.css'
export interface Props {
config: YogaSingleService_Plain
}
const OurServiceItemComponent = ({config: {header,description,image}}: Props) => {
const imageFile: StrapiFile = image as StrapiFile;
return (
<div className={styles.serviceSlide}>
{/*<div className="col-lg-3 col-md-6 col-sm-6 col-xs-12">*/}
<div className="services_box_content">
<div className="services_box_upper_portion">
<figure className="mb-0">
<YogaImageComponent src={strapiApi.getImageUrl(imageFile?.url)} alt="" className="img-fluid"/>
</figure>
</div>
<div className="services_box_lower_portion">
<h3>{header}</h3>
<p>{description}</p>
<div className="btn_wrapper">
<a href="/services" className="text-decoration-none"><i
className="fa-solid fa-arrow-right" aria-hidden="true"></i></a>
</div>
</div>
</div>
</div>
);
}
export default OurServiceItemComponent;

View File

@@ -7,27 +7,28 @@ export interface Props{
config: YogaPrice_Plain
}
export function PriceItemComponent({config: {header,option1,option2,price,icon, image,buttonText}} : Props){
export function PriceItemComponent({config: {header, description, option1,option2,price,pricePostfix, icon, image,buttonText}} : Props){
// there are some issues with the strapi generated types
const iconFile: StrapiFile = icon as StrapiFile;
const imageFile: StrapiFile = image as StrapiFile;
console.info("image:",strapiApi.getImageUrl(imageFile.url));
console.info("image:",strapiApi.getImageUrl(imageFile?.url));
return (
<div className="col-lg-4 col-md-4 col-sm-6 col-xs-12">
<div className="pricing_plans_box_content">
<div className="pricing_plans_box_upper_portion">
<figure className="pricing_plans_image mb-0">
<YogaImageComponent src={strapiApi.getImageUrl(imageFile.url)} alt="" className="img-fluid"/>
<YogaImageComponent src={strapiApi.getImageUrl(imageFile?.url)} alt="" className="img-fluid"/>
</figure>
<div className="pricing_plans_box_image_content">
<figure className="mb-0">
<YogaImageComponent src={strapiApi.getImageUrl(iconFile.url)} alt=""
<YogaImageComponent src={strapiApi.getImageUrl(iconFile?.url)} alt=""
className="img-fluid"/>
</figure>
</div>
</div>
<div className="pricing_plans_box_lower_portion">
<h3>{header}</h3>
<p className={'text-center'}>{description}</p>
<ul className="list-unstyled">
<li>
<i className="fa-solid fa-check" aria-hidden="true"></i>{option1}
@@ -38,7 +39,7 @@ export function PriceItemComponent({config: {header,option1,option2,price,icon,
</ul>
<div className="pricing_plans_span_wrapper">
<span className="price">{price} FT</span>
<span className="per_month">/per month</span>
{ pricePostfix && <span className="per_month">{pricePostfix}</span> }
</div>
<div className="btn_wrapper">
<a className="enroll_now_btn text-decoration-none" href="/pricing.html">{buttonText}</a>

View File

@@ -11,7 +11,7 @@ export default function TextWithRightImage ({config: {
}}: Props){
const strapiFile = image as StrapiFile;
const imageUrl = strapiApi.getImageUrl(strapiFile.url)
const imageUrl = strapiApi.getImageUrl(strapiFile?.url)
return (
<section className="mission_section">

View File

@@ -12,7 +12,7 @@ export default function TextWithLeftImage ({config: {
}}: Props){
const strapiFile = image as StrapiFile;
const imageUrl = strapiApi.getImageUrl(strapiFile.url)
const imageUrl = strapiApi.getImageUrl(strapiFile?.url);
return (

View File

@@ -10,6 +10,7 @@ export interface YogaAchivement {
createdAt: Date; updatedAt: Date; publishedAt?: Date; title?: string;
image?: { data: Media };
name?: string;
description?: string;
};
}
export interface YogaAchivement_Plain {
@@ -17,6 +18,7 @@ export interface YogaAchivement_Plain {
createdAt: Date; updatedAt: Date; publishedAt?: Date; title?: string;
image?: Media_Plain;
name?: string;
description?: string;
}
export interface YogaAchivement_NoRelations {
@@ -24,6 +26,7 @@ export interface YogaAchivement_NoRelations {
createdAt: Date; updatedAt: Date; publishedAt?: Date; title?: string;
image?: number;
name?: string;
description?: string;
}
export interface YogaAchivement_AdminPanelLifeCycle {
@@ -31,4 +34,5 @@ export interface YogaAchivement_AdminPanelLifeCycle {
createdAt: Date; updatedAt: Date; publishedAt?: Date; title?: string;
image?: AdminPanelRelationPropertyModification<Media_Plain>;
name?: string;
description?: string;
}

View File

@@ -14,6 +14,8 @@ export interface YogaPrice {
price?: number;
icon?: { data: Media };
image?: { data: Media };
pricePostfix?: string;
description?: string;
};
}
export interface YogaPrice_Plain {
@@ -25,6 +27,8 @@ export interface YogaPrice_Plain {
price?: number;
icon?: Media_Plain;
image?: Media_Plain;
pricePostfix?: string;
description?: string;
}
export interface YogaPrice_NoRelations {
@@ -36,6 +40,8 @@ export interface YogaPrice_NoRelations {
price?: number;
icon?: number;
image?: number;
pricePostfix?: string;
description?: string;
}
export interface YogaPrice_AdminPanelLifeCycle {
@@ -47,4 +53,6 @@ export interface YogaPrice_AdminPanelLifeCycle {
price?: number;
icon?: AdminPanelRelationPropertyModification<Media_Plain>;
image?: AdminPanelRelationPropertyModification<Media_Plain>;
pricePostfix?: string;
description?: string;
}

View File

@@ -13,6 +13,7 @@ export interface YogaSingleService {
image?: { data: Media };
imageAlt?: string;
name?: string;
article?: string;
locale: string;
localizations?: { data: YogaSingleService[] };
};
@@ -25,6 +26,7 @@ export interface YogaSingleService_Plain {
image?: Media_Plain;
imageAlt?: string;
name?: string;
article?: string;
locale: string;
localizations?: YogaSingleService_Plain[];
}
@@ -37,6 +39,7 @@ export interface YogaSingleService_NoRelations {
image?: number;
imageAlt?: string;
name?: string;
article?: string;
locale: string;
localizations?: YogaSingleService[];
}
@@ -49,6 +52,7 @@ export interface YogaSingleService_AdminPanelLifeCycle {
image?: AdminPanelRelationPropertyModification<Media_Plain>;
imageAlt?: string;
name?: string;
article?: string;
locale: string;
localizations?: YogaSingleService[];
}

View File

@@ -2,7 +2,7 @@ import {MenuItem} from "@/components/nav.component";
export const MAIN_MENU:MenuItem[] = [
{
label: 'Home',
label: 'Kezdőoldal',
href: '/'
},
{

View File

@@ -1,5 +1,5 @@
# Creating multi-stage build for production
FROM node:18-alpine as build
FROM --platform=linux/amd64 node:18-alpine as BUILDER
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git > /dev/null 2>&1
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
@@ -7,21 +7,21 @@ ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY package.json package-lock.json ./
RUN npm install -g node-gyp
RUN npm config set fetch-retry-maxtimeout 600000 -g && npm install --only=production --debug
RUN npm config set fetch-retry-maxtimeout 600000 -g && npm install --only=production
ENV PATH=/opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN npm run build --debug
RUN npm run build
# Creating final production image
FROM node:18-alpine
FROM --platform=linux/amd64 node:18-alpine
RUN apk add --no-cache vips-dev
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY --from=build /opt/node_modules ./node_modules
COPY --from=BUILDER /opt/node_modules ./node_modules
WORKDIR /opt/app
COPY --from=build /opt/app ./
COPY --from=BUILDER /opt/app ./
ENV PATH=/opt/node_modules/.bin:$PATH
RUN chown -R node:node /opt/app

View File

@@ -11,21 +11,20 @@ RUN npm config set fetch-retry-maxtimeout 600000 -g && npm install --only=produc
ENV PATH=/opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN pwd && ls -lah
RUN npm run build --debug
# Creating final production image
FROM node:18-alpine
# RUN apk add --no-cache vips-dev
# ARG NODE_ENV=production
# ENV NODE_ENV=${NODE_ENV}
# WORKDIR /opt/
# COPY --from=build /opt/node_modules ./node_modules
# WORKDIR /opt/app
# COPY --from=build /opt/app ./
# ENV PATH=/opt/node_modules/.bin:$PATH
RUN apk add --no-cache vips-dev
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY --from=build /opt/node_modules ./node_modules
WORKDIR /opt/app
COPY --from=build /opt/app ./
ENV PATH=/opt/node_modules/.bin:$PATH
# RUN chown -R node:node /opt/app
RUN chown -R node:node /opt/app
USER node
EXPOSE 1337
# CMD ["npm", "run", "start"]
CMD ["npm", "run", "start"]

Binary file not shown.

View File

@@ -10,6 +10,7 @@ export interface YogaAchivement {
createdAt: Date; updatedAt: Date; publishedAt?: Date; title?: string;
image?: { data: Media };
name?: string;
description?: string;
};
}
export interface YogaAchivement_Plain {
@@ -17,6 +18,7 @@ export interface YogaAchivement_Plain {
createdAt: Date; updatedAt: Date; publishedAt?: Date; title?: string;
image?: Media_Plain;
name?: string;
description?: string;
}
export interface YogaAchivement_NoRelations {
@@ -24,6 +26,7 @@ export interface YogaAchivement_NoRelations {
createdAt: Date; updatedAt: Date; publishedAt?: Date; title?: string;
image?: number;
name?: string;
description?: string;
}
export interface YogaAchivement_AdminPanelLifeCycle {
@@ -31,4 +34,5 @@ export interface YogaAchivement_AdminPanelLifeCycle {
createdAt: Date; updatedAt: Date; publishedAt?: Date; title?: string;
image?: AdminPanelRelationPropertyModification<Media_Plain>;
name?: string;
description?: string;
}

View File

@@ -14,6 +14,8 @@ export interface YogaPrice {
price?: number;
icon?: { data: Media };
image?: { data: Media };
pricePostfix?: string;
description?: string;
};
}
export interface YogaPrice_Plain {
@@ -25,6 +27,8 @@ export interface YogaPrice_Plain {
price?: number;
icon?: Media_Plain;
image?: Media_Plain;
pricePostfix?: string;
description?: string;
}
export interface YogaPrice_NoRelations {
@@ -36,6 +40,8 @@ export interface YogaPrice_NoRelations {
price?: number;
icon?: number;
image?: number;
pricePostfix?: string;
description?: string;
}
export interface YogaPrice_AdminPanelLifeCycle {
@@ -47,4 +53,6 @@ export interface YogaPrice_AdminPanelLifeCycle {
price?: number;
icon?: AdminPanelRelationPropertyModification<Media_Plain>;
image?: AdminPanelRelationPropertyModification<Media_Plain>;
pricePostfix?: string;
description?: string;
}

View File

@@ -13,6 +13,7 @@ export interface YogaSingleService {
image?: { data: Media };
imageAlt?: string;
name?: string;
article?: string;
locale: string;
localizations?: { data: YogaSingleService[] };
};
@@ -25,6 +26,7 @@ export interface YogaSingleService_Plain {
image?: Media_Plain;
imageAlt?: string;
name?: string;
article?: string;
locale: string;
localizations?: YogaSingleService_Plain[];
}
@@ -37,6 +39,7 @@ export interface YogaSingleService_NoRelations {
image?: number;
imageAlt?: string;
name?: string;
article?: string;
locale: string;
localizations?: YogaSingleService[];
}
@@ -49,6 +52,7 @@ export interface YogaSingleService_AdminPanelLifeCycle {
image?: AdminPanelRelationPropertyModification<Media_Plain>;
imageAlt?: string;
name?: string;
article?: string;
locale: string;
localizations?: YogaSingleService[];
}

File diff suppressed because it is too large Load Diff

View File

@@ -13,9 +13,9 @@
},
"dependencies": {
"@ckeditor/strapi-plugin-ckeditor": "^1.1.0",
"@strapi/plugin-cloud": "5.6.0",
"@strapi/plugin-users-permissions": "5.6.0",
"@strapi/strapi": "5.6.0",
"@strapi/plugin-cloud": "5.13.0",
"@strapi/plugin-users-permissions": "5.13.0",
"@strapi/strapi": "5.13.0",
"better-sqlite3": "11.3.0",
"fs-extra": "^10.0.0",
"mime-types": "^2.1.27",
@@ -23,6 +23,7 @@
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-router-dom": "^6.0.0",
"sharp": "^0.33.5",
"strapi-import-export": "^0.0.1",
"strapi-plugin-schemas-to-ts": "^1.3.2",
"styled-components": "^6.0.0"

View File

@@ -28,6 +28,9 @@
},
"name": {
"type": "string"
},
"description": {
"type": "text"
}
}
}

View File

@@ -4,7 +4,8 @@
"info": {
"singularName": "yoga-price",
"pluralName": "yoga-prices",
"displayName": "YogaPrice"
"displayName": "YogaPrice",
"description": ""
},
"options": {
"draftAndPublish": true
@@ -27,24 +28,32 @@
"type": "integer"
},
"icon": {
"type": "media",
"multiple": false,
"required": false,
"allowedTypes": [
"images",
"files",
"videos",
"audios"
],
"type": "media",
"multiple": false
]
},
"image": {
"type": "media",
"multiple": false,
"required": false,
"allowedTypes": [
"images",
"files",
"videos",
"audios"
],
"type": "media",
"multiple": false
]
},
"pricePostfix": {
"type": "string"
},
"description": {
"type": "text"
}
}
}

View File

@@ -4,7 +4,8 @@
"info": {
"singularName": "yoga-single-service",
"pluralName": "yoga-single-services",
"displayName": "YogaSingleService"
"displayName": "YogaSingleService",
"description": ""
},
"options": {
"draftAndPublish": true
@@ -40,14 +41,15 @@
"type": "string"
},
"image": {
"type": "media",
"multiple": false,
"required": false,
"allowedTypes": [
"images",
"files",
"videos",
"audios"
],
"type": "media",
"multiple": false,
"pluginOptions": {
"i18n": {
"localized": true
@@ -69,6 +71,14 @@
}
},
"type": "string"
},
"article": {
"pluginOptions": {
"i18n": {
"localized": true
}
},
"type": "richtext"
}
}
}

View File

@@ -34,6 +34,10 @@ export interface AdminApiToken extends Struct.CollectionTypeSchema {
minLength: 1;
}> &
Schema.Attribute.DefaultTo<''>;
encryptedKey: Schema.Attribute.Text &
Schema.Attribute.SetMinMaxLength<{
minLength: 1;
}>;
expiresAt: Schema.Attribute.DateTime;
lastUsedAt: Schema.Attribute.DateTime;
lifespan: Schema.Attribute.BigInteger;
@@ -1038,6 +1042,7 @@ export interface ApiYogaAchivementYogaAchivement
createdAt: Schema.Attribute.DateTime;
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
description: Schema.Attribute.Text;
image: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios'>;
locale: Schema.Attribute.String & Schema.Attribute.Private;
localizations: Schema.Attribute.Relation<
@@ -1637,6 +1642,7 @@ export interface ApiYogaPriceComponentYogaPriceComponent
export interface ApiYogaPriceYogaPrice extends Struct.CollectionTypeSchema {
collectionName: 'yoga_prices';
info: {
description: '';
displayName: 'YogaPrice';
pluralName: 'yoga-prices';
singularName: 'yoga-price';
@@ -1649,6 +1655,7 @@ export interface ApiYogaPriceYogaPrice extends Struct.CollectionTypeSchema {
createdAt: Schema.Attribute.DateTime;
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
description: Schema.Attribute.Text;
header: Schema.Attribute.String;
icon: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios'>;
image: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios'>;
@@ -1661,6 +1668,7 @@ export interface ApiYogaPriceYogaPrice extends Struct.CollectionTypeSchema {
option1: Schema.Attribute.String;
option2: Schema.Attribute.String;
price: Schema.Attribute.Integer;
pricePostfix: Schema.Attribute.String;
publishedAt: Schema.Attribute.DateTime;
updatedAt: Schema.Attribute.DateTime;
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
@@ -1672,6 +1680,7 @@ export interface ApiYogaSingleServiceYogaSingleService
extends Struct.CollectionTypeSchema {
collectionName: 'yoga_single_services';
info: {
description: '';
displayName: 'YogaSingleService';
pluralName: 'yoga-single-services';
singularName: 'yoga-single-service';
@@ -1685,6 +1694,12 @@ export interface ApiYogaSingleServiceYogaSingleService
};
};
attributes: {
article: Schema.Attribute.RichText &
Schema.Attribute.SetPluginOptions<{
i18n: {
localized: true;
};
}>;
buttonLink: Schema.Attribute.String &
Schema.Attribute.SetPluginOptions<{
i18n: {