diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..5b75f16 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,12 @@ +FROM node:22-alpine AS build +WORKDIR /app +COPY package*.json ./ +RUN corepack enable +RUN pnpm install +COPY . . +RUN pnpm build + +FROM nginx:alpine AS runtime +COPY ./nginx/nginx.conf /etc/nginx/nginx.conf +COPY --from=build /app/dist /usr/share/nginx/html +EXPOSE 8080 \ No newline at end of file diff --git a/frontend/Makefile b/frontend/Makefile new file mode 100644 index 0000000..85d629e --- /dev/null +++ b/frontend/Makefile @@ -0,0 +1,18 @@ +dev: + pnpm dev + +build: + pnpm build + +docker: + docker compose up -d + +favicon: + node ./src/@dasig/scripts/node/generateFavicon.js + +logo: + node ./src/@dasig/scripts/node/optimizeLogo.js --size $(size) + +image: + node ./src/@dasig/scripts/node/optimizeImage.js --name $(name) --size $(size) + diff --git a/frontend/configs/design.site.sass b/frontend/configs/design.site.sass index 3035e27..d14273e 100644 --- a/frontend/configs/design.site.sass +++ b/frontend/configs/design.site.sass @@ -1,2 +1,6 @@ -$lightBackground: #dae6f6 -$darkBackground: #10121a +$lightBackground: #d4e0f0 +$darkBackground: #11141e + +$mobile: 575.98px +$tablet: 768px +$desktop: 1440px diff --git a/frontend/docker-compose.yml b/frontend/docker-compose.yml new file mode 100644 index 0000000..a9b3c4c --- /dev/null +++ b/frontend/docker-compose.yml @@ -0,0 +1,9 @@ +services: + template: + container_name: template + restart: unless-stopped + build: + context: . + dockerfile: Dockerfile + ports: + - 8080:8080 diff --git a/frontend/nginx/nginx.conf b/frontend/nginx/nginx.conf new file mode 100644 index 0000000..a1a6187 --- /dev/null +++ b/frontend/nginx/nginx.conf @@ -0,0 +1,31 @@ +worker_processes 1; + +events { + worker_connections 1024; +} + +http { + server { + listen 8080; + server_name _; + + root /usr/share/nginx/html; + index index.html index.htm; + include /etc/nginx/mime.types; + + gzip on; + gzip_min_length 1000; + gzip_proxied expired no-cache no-store private auth; + gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; + + error_page 404 /404.html; + location = /404.html { + root /usr/share/nginx/html; + internal; + } + + location / { + try_files $uri $uri/index.html =404; + } + } +} \ No newline at end of file diff --git a/frontend/node_scripts/generateFavicon.js b/frontend/node_scripts/generateFavicon.js deleted file mode 100644 index c64f651..0000000 --- a/frontend/node_scripts/generateFavicon.js +++ /dev/null @@ -1,21 +0,0 @@ -import { consola } from 'consola'; -import * as fs from 'fs'; -import * as path from 'path'; -import sharp from 'sharp'; -(async () => { - try { - const dirPath = path.resolve('../../../public') - - if (fs.existsSync(dirPath)) { - const inputSrc = '../../assets/images/logo.png' - const favicon = dirPath + '/favicon.png' - const faviconBuffer = await sharp(inputSrc).png({ quality: 90 }).resize(50).toBuffer() - await sharp(faviconBuffer).toFile(favicon) - consola.success('Favicon generated successfully') - } else { - consola.error('Directory does not exist:', dirPath) - } - } catch (error) { - consola.error('Error generating favicon:', error) - } -})() diff --git a/frontend/package.json b/frontend/package.json index a6dd07c..e15be4b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -5,20 +5,25 @@ "dev": "vinxi dev", "build": "vinxi build", "start": "vinxi start", - "version": "vinxi version" + "version": "vinxi version", + "favicon": "node ./src/@dasig/scripts/node/generateFavicon.js" }, "dependencies": { "@solidjs/meta": "^0.29.4", "@solidjs/router": "^0.15.0", "@solidjs/start": "^1.1.0", + "consola": "^3.4.2", "dayjs": "^1.11.19", "eciesjs": "^0.4.16", "jsencrypt": "^3.5.4", "nanostores": "^1.1.0", "ofetch": "^1.5.1", + "png-to-ico": "^3.0.1", + "sharp": "^0.34.5", "solid-icons": "^1.1.0", "solid-js": "^1.9.5", - "vinxi": "^0.5.7" + "vinxi": "^0.5.7", + "yargs": "^18.0.0" }, "engines": { "node": ">=22" diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index c501a50..7384b04 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@solidjs/start': specifier: ^1.1.0 version: 1.2.0(solid-js@1.9.9)(vinxi@0.5.8(@types/node@24.7.2)(db0@0.3.4)(ioredis@5.8.1)(jiti@2.6.1)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.0))(vite@6.4.0(@types/node@24.7.2)(jiti@2.6.1)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.0)) + consola: + specifier: ^3.4.2 + version: 3.4.2 dayjs: specifier: ^1.11.19 version: 1.11.19 @@ -32,6 +35,12 @@ importers: ofetch: specifier: ^1.5.1 version: 1.5.1 + png-to-ico: + specifier: ^3.0.1 + version: 3.0.1 + sharp: + specifier: ^0.34.5 + version: 0.34.5 solid-icons: specifier: ^1.1.0 version: 1.1.0(solid-js@1.9.9) @@ -41,6 +50,9 @@ importers: vinxi: specifier: ^0.5.7 version: 0.5.8(@types/node@24.7.2)(db0@0.3.4)(ioredis@5.8.1)(jiti@2.6.1)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.0) + yargs: + specifier: ^18.0.0 + version: 18.0.0 devDependencies: '@biomejs/biome': specifier: ^2.3.6 @@ -263,6 +275,9 @@ packages: peerDependencies: '@noble/ciphers': ^1.0.0 + '@emnapi/runtime@1.7.1': + resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} + '@esbuild/aix-ppc64@0.25.11': resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} engines: {node: '>=18'} @@ -419,6 +434,143 @@ packages: cpu: [x64] os: [win32] + '@img/colour@1.0.0': + resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.4': + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.2.4': + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.2.4': + resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-riscv64@1.2.4': + resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + cpu: [riscv64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.2.4': + resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.2.4': + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.34.5': + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.34.5': + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-ppc64@0.34.5': + resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-riscv64@0.34.5': + resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [riscv64] + os: [linux] + + '@img/sharp-linux-s390x@0.34.5': + resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.34.5': + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.34.5': + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.34.5': + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.34.5': + resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.5': + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@ioredis/commands@1.4.0': resolution: {integrity: sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==} @@ -855,6 +1007,9 @@ packages: '@types/micromatch@4.0.9': resolution: {integrity: sha512-7V+8ncr22h4UoYRLnLXSpTxjQrNUXtWHGeMPRJt1nULXI57G9bIcpyrHlmrQ7QK24EyyuXvYcSSWAM8GA9nqCg==} + '@types/node@22.19.1': + resolution: {integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==} + '@types/node@24.7.2': resolution: {integrity: sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==} @@ -1097,6 +1252,10 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} + cliui@9.0.1: + resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} + engines: {node: '>=20'} + cluster-key-slot@1.1.2: resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} engines: {node: '>=0.10.0'} @@ -1769,6 +1928,9 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -1931,6 +2093,15 @@ packages: pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + png-to-ico@3.0.1: + resolution: {integrity: sha512-S8BOAoaGd9gT5uaemQ62arIY3Jzco7Uc7LwUTqRyqJDTsKqOAiyfyN4dSdT0D+Zf8XvgztgpRbM5wnQd7EgYwg==} + engines: {node: '>=20'} + hasBin: true + + pngjs@7.0.0: + resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} + engines: {node: '>=14.19.0'} + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -2214,6 +2385,10 @@ packages: setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + sharp@0.34.5: + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -2428,6 +2603,9 @@ packages: undici-types@5.28.4: resolution: {integrity: sha512-3OeMF5Lyowe8VW0skf5qaIE7Or3yS9LS7fvMUI0gg4YxpIBVg0L8BxCmROw2CcYhSkpR68Epz7CGc8MPj94Uww==} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.14.0: resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==} @@ -2677,10 +2855,18 @@ packages: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yargs@18.0.0: + resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + youch-core@0.3.3: resolution: {integrity: sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==} @@ -2947,6 +3133,11 @@ snapshots: dependencies: '@noble/ciphers': 1.3.0 + '@emnapi/runtime@1.7.1': + dependencies: + tslib: 2.8.1 + optional: true + '@esbuild/aix-ppc64@0.25.11': optional: true @@ -3025,6 +3216,102 @@ snapshots: '@esbuild/win32-x64@0.25.11': optional: true + '@img/colour@1.0.0': {} + + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true + + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true + + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true + + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.7.1 + optional: true + + '@img/sharp-win32-arm64@0.34.5': + optional: true + + '@img/sharp-win32-ia32@0.34.5': + optional: true + + '@img/sharp-win32-x64@0.34.5': + optional: true + '@ioredis/commands@1.4.0': {} '@isaacs/cliui@8.0.2': @@ -3463,6 +3750,10 @@ snapshots: dependencies: '@types/braces': 3.0.5 + '@types/node@22.19.1': + dependencies: + undici-types: 6.21.0 + '@types/node@24.7.2': dependencies: undici-types: 7.14.0 @@ -3747,6 +4038,12 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + cliui@9.0.1: + dependencies: + string-width: 7.2.0 + strip-ansi: 7.1.2 + wrap-ansi: 9.0.2 + cluster-key-slot@1.1.2: {} color-convert@2.0.1: @@ -4364,6 +4661,8 @@ snapshots: dependencies: brace-expansion: 2.0.2 + minimist@1.2.8: {} + minipass@7.1.2: {} minizlib@3.1.0: @@ -4596,6 +4895,14 @@ snapshots: exsolve: 1.0.7 pathe: 2.0.3 + png-to-ico@3.0.1: + dependencies: + '@types/node': 22.19.1 + minimist: 1.2.8 + pngjs: 7.0.0 + + pngjs@7.0.0: {} + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -4910,6 +5217,37 @@ snapshots: setprototypeof@1.2.0: {} + sharp@0.34.5: + dependencies: + '@img/colour': 1.0.0 + detect-libc: 2.1.2 + semver: 7.7.3 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-ppc64': 0.34.5 + '@img/sharp-linux-riscv64': 0.34.5 + '@img/sharp-linux-s390x': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-wasm32': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-ia32': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -5128,6 +5466,8 @@ snapshots: undici-types@5.28.4: {} + undici-types@6.21.0: {} + undici-types@7.14.0: {} unenv@1.10.0: @@ -5422,6 +5762,8 @@ snapshots: yargs-parser@21.1.1: {} + yargs-parser@22.0.0: {} + yargs@17.7.2: dependencies: cliui: 8.0.1 @@ -5432,6 +5774,15 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yargs@18.0.0: + dependencies: + cliui: 9.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + string-width: 7.2.0 + y18n: 5.0.8 + yargs-parser: 22.0.0 + youch-core@0.3.3: dependencies: '@poppinss/exception': 1.2.2 diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico deleted file mode 100644 index fb282da..0000000 Binary files a/frontend/public/favicon.ico and /dev/null differ diff --git a/frontend/public/favicon.png b/frontend/public/favicon.png new file mode 100644 index 0000000..2fc620c Binary files /dev/null and b/frontend/public/favicon.png differ diff --git a/frontend/src/@dasig/components/Copyright.tsx b/frontend/src/@dasig/components/Copyright.tsx index 89d5d1b..7ecb7d6 100644 --- a/frontend/src/@dasig/components/Copyright.tsx +++ b/frontend/src/@dasig/components/Copyright.tsx @@ -1,4 +1,4 @@ -import { $companyName, $copyRightYear } from "configs/config.site" +import { $companyName, $copyRightYear } from "../../../configs/config.site" export default () => { return ( diff --git a/frontend/src/@dasig/components/Display.tsx b/frontend/src/@dasig/components/Display.tsx new file mode 100644 index 0000000..704405e --- /dev/null +++ b/frontend/src/@dasig/components/Display.tsx @@ -0,0 +1,41 @@ +import { type JSXElement, Match, Switch } from 'solid-js' +import '../styles/Display.sass' + +interface Props { + children: JSXElement + desktop?: boolean + tablet?: boolean + mobile?: boolean +} + +export default (props: Props) => { + return ( + <> + + +
{props.children}
+
+ + +
{props.children}
+
+ + +
{props.children}
+
+ + +
{props.children}
+
+ + +
{props.children}
+
+ + +
{props.children}
+
+
+ + ) +} diff --git a/frontend/src/@dasig/components/HTML.tsx b/frontend/src/@dasig/components/HTML.tsx index 3f8af84..7e5906c 100644 --- a/frontend/src/@dasig/components/HTML.tsx +++ b/frontend/src/@dasig/components/HTML.tsx @@ -30,7 +30,7 @@ export default (props: Props) => { - + diff --git a/frontend/src/@dasig/components/Padding.tsx b/frontend/src/@dasig/components/Padding.tsx new file mode 100644 index 0000000..d55e3c1 --- /dev/null +++ b/frontend/src/@dasig/components/Padding.tsx @@ -0,0 +1,13 @@ +import { type JSXElement } from 'solid-js' + +interface Props { + left: number + right: number + top: number + bottom: number + children: JSXElement +} + +export default (props: Props) => { + return
{props.children}
+} diff --git a/frontend/src/@dasig/images/logo.avif b/frontend/src/@dasig/images/logo.avif index dc7b89e..2597894 100644 Binary files a/frontend/src/@dasig/images/logo.avif and b/frontend/src/@dasig/images/logo.avif differ diff --git a/frontend/src/@dasig/images/logo.webp b/frontend/src/@dasig/images/logo.webp index 484b34f..8fb02ce 100644 Binary files a/frontend/src/@dasig/images/logo.webp and b/frontend/src/@dasig/images/logo.webp differ diff --git a/frontend/src/@dasig/images/ocbologo2.avif b/frontend/src/@dasig/images/ocbologo2.avif new file mode 100644 index 0000000..1c093b7 Binary files /dev/null and b/frontend/src/@dasig/images/ocbologo2.avif differ diff --git a/frontend/src/@dasig/images/ocbologo2.webp b/frontend/src/@dasig/images/ocbologo2.webp new file mode 100644 index 0000000..63e4ec1 Binary files /dev/null and b/frontend/src/@dasig/images/ocbologo2.webp differ diff --git a/frontend/src/@dasig/index.ts b/frontend/src/@dasig/index.ts index dd7a0b8..e5c535b 100644 --- a/frontend/src/@dasig/index.ts +++ b/frontend/src/@dasig/index.ts @@ -1,3 +1,5 @@ export { default as Column } from './components/Column' +export { default as Display } from './components/Display' export { default as HTML } from './components/HTML' export { default as Page } from './components/Page' + diff --git a/frontend/src/@dasig/scripts/node/generateFavicon.js b/frontend/src/@dasig/scripts/node/generateFavicon.js new file mode 100644 index 0000000..6a75e0f --- /dev/null +++ b/frontend/src/@dasig/scripts/node/generateFavicon.js @@ -0,0 +1,23 @@ +import { consola } from 'consola'; +import * as fs from 'fs'; +import * as path from 'path'; +import sharp from 'sharp'; + +try { + const dirPath = path.resolve('./public') + + if (fs.existsSync(dirPath)) { + const inputSrc = './src/images/favicon.png' + const favicon = dirPath + '/favicon.png' + const faviconBuffer = await sharp(inputSrc).png({ quality: 90 }).resize(48).toBuffer() + await sharp(faviconBuffer).toFile(favicon) + consola.success('Favicon generated successfully') + } else { + consola.error('Directory does not exist:', dirPath) + } + +} catch (error) { + if (error.message.includes('missing')) { + consola.error('Source favicon does not exist') + } +} diff --git a/frontend/src/@dasig/scripts/node/optimizeImage.js b/frontend/src/@dasig/scripts/node/optimizeImage.js new file mode 100644 index 0000000..439f907 --- /dev/null +++ b/frontend/src/@dasig/scripts/node/optimizeImage.js @@ -0,0 +1,41 @@ +import { consola } from 'consola'; +import sharp from 'sharp'; +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; + +(async () => { + const argv = yargs(hideBin(process.argv)) + .option('name', { + alias: 'n', + describe: 'Specify the name of the image', + type: 'string', + demandOption: true, + }) + .option('size', { + alias: 's', + describe: 'Specify the size of the image', + type: 'number', + demandOption: true, + }) + .argv; + + const name = argv.name; + const size = argv.size; + + try { + const avifOutputPath = `./src/@dasig/images/${name.toString().split('.').slice(0, -1).join('.')}.avif` + const webpOutputPath = `./src/@dasig/images/${name.toString().split('.').slice(0, -1).join('.')}.webp` + + const avifBuffer = await sharp(`./src/images/${name}`).avif({ quality: 60 }).resize(size).toBuffer() + await sharp(avifBuffer).toFile(avifOutputPath) + consola.success(`${name} successfully optimized in Avif`) + + const webpBuffer = await sharp(`./src/images/${name}`).webp({ quality: 75 }).resize(size).toBuffer() + await sharp(webpBuffer).toFile(webpOutputPath) + consola.success(`${name} successfully optimized in Webp`) + } catch (error) { + consola.error('Error optimizing image:', error) + if (error.message.includes('missing')) consola.error(`${name} could not be found on image folder`) + } +})() + diff --git a/frontend/src/@dasig/scripts/node/optimizeLogo.js b/frontend/src/@dasig/scripts/node/optimizeLogo.js new file mode 100644 index 0000000..5a62dce --- /dev/null +++ b/frontend/src/@dasig/scripts/node/optimizeLogo.js @@ -0,0 +1,33 @@ +import { consola } from 'consola'; +import sharp from 'sharp'; +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; + +(async () => { + const argv = yargs(hideBin(process.argv)) + .option('size', { + alias: 's', + describe: 'Specify the size of the logo', + type: 'number', + demandOption: true, + }) + .argv; + + const size = argv.size; + + try { + const webpImage = './src/@dasig/images/logo.webp' + const avifImage = './src/@dasig/images/logo.avif' + const inputSrc = './src/images/logo.png' + + const avifBuffer = await sharp(inputSrc).avif({ quality: 60 }).resize(size).toBuffer() + await sharp(avifBuffer).toFile(avifImage) + consola.success('Logo successfully optimized in Avif') + + const webpBuffer = await sharp(inputSrc).webp({ quality: 75 }).resize(size).toBuffer() + await sharp(webpBuffer).toFile(webpImage) + consola.success('Logo successfully optimized in Webp') + } catch (error) { + consola.error('Error generating favicon:', error) + } +})() diff --git a/frontend/src/@dasig/styles/Display.sass b/frontend/src/@dasig/styles/Display.sass new file mode 100644 index 0000000..b0c0a83 --- /dev/null +++ b/frontend/src/@dasig/styles/Display.sass @@ -0,0 +1 @@ +@use '../../styles/breakpoint.sass' diff --git a/frontend/src/assets/images/favicon.png b/frontend/src/assets/images/favicon.png deleted file mode 100644 index 85716bb..0000000 Binary files a/frontend/src/assets/images/favicon.png and /dev/null differ diff --git a/frontend/src/components/Counter/Counter.sass b/frontend/src/components/Counter.sass similarity index 90% rename from frontend/src/components/Counter/Counter.sass rename to frontend/src/components/Counter.sass index 755fcb2..28c40be 100644 --- a/frontend/src/components/Counter/Counter.sass +++ b/frontend/src/components/Counter.sass @@ -1,6 +1,6 @@ @use 'sass:color' -@use '../../../configs/design.site' as design -@use '../../styles/functions' as func +@use '../../configs/design.site' as design +@use '../styles/functions' as func .counter font-family: inherit @@ -20,7 +20,7 @@ &__display font-size: 1.75rem - font-weight: 200 + font-weight: 300 &__buttons display: flex diff --git a/frontend/src/components/Counter/Counter.tsx b/frontend/src/components/Counter.tsx similarity index 100% rename from frontend/src/components/Counter/Counter.tsx rename to frontend/src/components/Counter.tsx diff --git a/frontend/src/images/logo.png b/frontend/src/images/logo.png new file mode 100644 index 0000000..48cee2a Binary files /dev/null and b/frontend/src/images/logo.png differ diff --git a/frontend/src/images/ocbologo2.png b/frontend/src/images/ocbologo2.png new file mode 100755 index 0000000..842c682 Binary files /dev/null and b/frontend/src/images/ocbologo2.png differ diff --git a/frontend/src/routes/index.tsx b/frontend/src/routes/index.tsx index 7f3869f..aef80ec 100644 --- a/frontend/src/routes/index.tsx +++ b/frontend/src/routes/index.tsx @@ -1,5 +1,5 @@ import { Column, Page } from '~/@dasig' -import Counter from '~/components/Counter/Counter' +import Counter from '~/components/Counter' import './index.sass' export default () => { diff --git a/frontend/src/styles/breakpoint.sass b/frontend/src/styles/breakpoint.sass index 738c1a2..f86ffef 100644 --- a/frontend/src/styles/breakpoint.sass +++ b/frontend/src/styles/breakpoint.sass @@ -1,51 +1,49 @@ -$mobile: 575.98px -$tablet: 768px -$desktop: 1440px +@use '../../configs/design.site' as design .on-desktop-only - @media only screen and (min-width: 0px) and (max-width: $desktop) + @media only screen and (min-width: 0px) and (max-width: design.$desktop) display: none - @media only screen and (min-width: $desktop) + @media only screen and (min-width: design.$desktop) display: block .on-tablet-only - @media only screen and (min-width: 0px) and (max-width: $tablet) + @media only screen and (min-width: 0px) and (max-width: design.$tablet) display: none - @media only screen and (min-width: $tablet) and (max-width: $desktop) + @media only screen and (min-width: design.$tablet) and (max-width: design.$desktop) display: block - @media only screen and (min-width: $desktop) + @media only screen and (min-width: design.$desktop) display: none .on-mobile-only - @media only screen and (max-width: $mobile) + @media only screen and (max-width: design.$mobile) display: block - @media only screen and (min-width: $tablet) + @media only screen and (min-width: design.$tablet) display: none .on-desktop-tablet-only - @media only screen and (min-width: 0px) and (max-width: $tablet) + @media only screen and (min-width: 0px) and (max-width: design.$tablet) display: none - @media only screen and (min-width: $tablet) + @media only screen and (min-width: design.$tablet) display: block .on-desktop-mobile-only - @media only screen and (min-width: 0px) and (max-width: $mobile) + @media only screen and (min-width: 0px) and (max-width: design.$mobile) display: block - @media only screen and (min-width: $mobile) and (max-width: $desktop) + @media only screen and (min-width: design.$mobile) and (max-width: design.$desktop) display: none - @media only screen and (min-width: $desktop) + @media only screen and (min-width: design.$desktop) display: block .on-tablet-mobile-only - @media only screen and (min-width: 0px) and (max-width: $desktop) + @media only screen and (min-width: 0px) and (max-width: design.$desktop) display: block - @media only screen and (min-width: $desktop) + @media only screen and (min-width: design.$desktop) display: none diff --git a/frontend/src/styles/functions.sass b/frontend/src/styles/functions.sass index c709d2c..4633406 100644 --- a/frontend/src/styles/functions.sass +++ b/frontend/src/styles/functions.sass @@ -1,5 +1,7 @@ +@use 'sass:color' + @function lighten-color($hex, $amount) - @return mix(white, $hex, $amount) + @return color.mix(white, $hex, $amount) @function darken-color($hex, $amount) - @return mix(black, $hex, $amount) + @return color.mix(black, $hex, $amount)