18 Commits

Author SHA1 Message Date
028297a4fe Update composer
All checks were successful
/ deploy-job (push) Successful in 2s
2026-03-06 08:57:40 +01:00
c16ab192ed Add scrape time to footer
All checks were successful
/ deploy-job (push) Successful in 1s
2026-03-04 07:33:10 +01:00
fc89944cf1 Fix badges colors
All checks were successful
/ deploy-job (push) Successful in 0s
2026-03-03 08:47:23 +01:00
a3b36df64e Fix badges colors 2026-03-03 08:47:23 +01:00
ce1fa049d1 Merge pull request 'feature/dark-theme' (#75) from feature/dark-theme into master
All checks were successful
/ deploy-job (push) Successful in 1s
2026-03-01 15:11:23 +01:00
f01398603d Merge branch 'refs/heads/master' into feature/dark-theme
# Conflicts:
#	templates/template.html.twig
2026-03-01 11:35:37 +01:00
8a520b11d6 Add footer with switch. 2026-03-01 10:46:47 +01:00
7eb9d42f97 Trigger action only on push to master
All checks were successful
/ deploy-job (push) Successful in 0s
2026-02-20 08:46:44 +01:00
52c16470e6 Add update script. 2026-02-20 08:46:44 +01:00
ad0ef20fc2 Country badge.
All checks were successful
/ deploy-job (push) Successful in 1s
2026-02-19 09:33:56 +01:00
e68389bccc Add locale badges to promos 2026-02-19 09:33:56 +01:00
e1dbdc539b Badges as links 2026-02-19 09:33:56 +01:00
f0f26ad64d Badges as links 2026-02-19 09:33:56 +01:00
c6c11d5f7f Merge pull request 'Add the rest of available countries.' (#48) from feature/new-countries into master
All checks were successful
/ deploy-job (push) Successful in 0s
2026-02-17 09:34:55 +01:00
7373657d78 Merge branch 'refs/heads/master' into feature/new-countries
All checks were successful
/ deploy-job (push) Successful in 0s
# Conflicts:
#	src/Command/Migrate.php
#	templates/product.html.twig
#	templates/productList.html.twig
2026-02-17 09:32:38 +01:00
ddc4cf9997 Start working on dark theme 2026-01-30 15:51:40 +01:00
3bbf82f897 Start working on handling multiple countries at once 2026-01-19 08:40:01 +01:00
a388b53cff Add the rest of available countries. 2026-01-19 08:33:19 +01:00
10 changed files with 271 additions and 119 deletions

View File

@@ -1,5 +1,7 @@
on: on:
push: push:
branches:
- master
workflow_dispatch: workflow_dispatch:
jobs: jobs:
deploy-job: deploy-job:

200
composer.lock generated
View File

@@ -1616,16 +1616,16 @@
}, },
{ {
"name": "symfony/cache", "name": "symfony/cache",
"version": "v8.0.5", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/cache.git", "url": "https://github.com/symfony/cache.git",
"reference": "92e9960386c7e01f58198038c199d522959a843c" "reference": "59184fa14658d7724cd9b8743d91c1b1aa618bff"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/cache/zipball/92e9960386c7e01f58198038c199d522959a843c", "url": "https://api.github.com/repos/symfony/cache/zipball/59184fa14658d7724cd9b8743d91c1b1aa618bff",
"reference": "92e9960386c7e01f58198038c199d522959a843c", "reference": "59184fa14658d7724cd9b8743d91c1b1aa618bff",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1692,7 +1692,7 @@
"psr6" "psr6"
], ],
"support": { "support": {
"source": "https://github.com/symfony/cache/tree/v8.0.5" "source": "https://github.com/symfony/cache/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -1712,7 +1712,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-27T16:18:07+00:00" "time": "2026-02-21T23:29:37+00:00"
}, },
{ {
"name": "symfony/cache-contracts", "name": "symfony/cache-contracts",
@@ -1869,16 +1869,16 @@
}, },
{ {
"name": "symfony/config", "name": "symfony/config",
"version": "v8.0.4", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/config.git", "url": "https://github.com/symfony/config.git",
"reference": "8f45af92f08f82902827a8b6f403aaf49d893539" "reference": "94ea198de42f93dffa920a098cac3961a82e63b7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/8f45af92f08f82902827a8b6f403aaf49d893539", "url": "https://api.github.com/repos/symfony/config/zipball/94ea198de42f93dffa920a098cac3961a82e63b7",
"reference": "8f45af92f08f82902827a8b6f403aaf49d893539", "reference": "94ea198de42f93dffa920a098cac3961a82e63b7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1923,7 +1923,7 @@
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/config/tree/v8.0.4" "source": "https://github.com/symfony/config/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -1943,20 +1943,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-13T13:06:50+00:00" "time": "2026-02-25T16:59:43+00:00"
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v8.0.4", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "ace03c4cf9805080ff40cbeec69fca180c339a3b" "reference": "488285876e807a4777f074041d8bb508623419fa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/ace03c4cf9805080ff40cbeec69fca180c339a3b", "url": "https://api.github.com/repos/symfony/console/zipball/488285876e807a4777f074041d8bb508623419fa",
"reference": "ace03c4cf9805080ff40cbeec69fca180c339a3b", "reference": "488285876e807a4777f074041d8bb508623419fa",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2013,7 +2013,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v8.0.4" "source": "https://github.com/symfony/console/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -2033,20 +2033,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-13T13:06:50+00:00" "time": "2026-02-25T16:59:43+00:00"
}, },
{ {
"name": "symfony/dependency-injection", "name": "symfony/dependency-injection",
"version": "v8.0.5", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/dependency-injection.git", "url": "https://github.com/symfony/dependency-injection.git",
"reference": "40a6c455ade7e3bf25900d6b746d40cfa2573e26" "reference": "edd98864a7b9eaaa10f389bd414e7d9e816bb59d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/40a6c455ade7e3bf25900d6b746d40cfa2573e26", "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/edd98864a7b9eaaa10f389bd414e7d9e816bb59d",
"reference": "40a6c455ade7e3bf25900d6b746d40cfa2573e26", "reference": "edd98864a7b9eaaa10f389bd414e7d9e816bb59d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2094,7 +2094,7 @@
"description": "Allows you to standardize and centralize the way objects are constructed in your application", "description": "Allows you to standardize and centralize the way objects are constructed in your application",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/dependency-injection/tree/v8.0.5" "source": "https://github.com/symfony/dependency-injection/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -2114,7 +2114,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-27T16:18:07+00:00" "time": "2026-02-25T16:59:43+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
@@ -2185,16 +2185,16 @@
}, },
{ {
"name": "symfony/dotenv", "name": "symfony/dotenv",
"version": "v8.0.0", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/dotenv.git", "url": "https://github.com/symfony/dotenv.git",
"reference": "460b4067a85288c59a59ce8c1bfb3942e71fd85c" "reference": "94d59769b0ea491dd8b635089e766519d28773d6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/dotenv/zipball/460b4067a85288c59a59ce8c1bfb3942e71fd85c", "url": "https://api.github.com/repos/symfony/dotenv/zipball/94d59769b0ea491dd8b635089e766519d28773d6",
"reference": "460b4067a85288c59a59ce8c1bfb3942e71fd85c", "reference": "94d59769b0ea491dd8b635089e766519d28773d6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2235,7 +2235,7 @@
"environment" "environment"
], ],
"support": { "support": {
"source": "https://github.com/symfony/dotenv/tree/v8.0.0" "source": "https://github.com/symfony/dotenv/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -2255,7 +2255,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-11-16T10:17:21+00:00" "time": "2026-02-13T12:00:38+00:00"
}, },
{ {
"name": "symfony/error-handler", "name": "symfony/error-handler",
@@ -2501,16 +2501,16 @@
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v8.0.1", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "d937d400b980523dc9ee946bb69972b5e619058d" "reference": "7bf9162d7a0dff98d079b72948508fa48018a770"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/d937d400b980523dc9ee946bb69972b5e619058d", "url": "https://api.github.com/repos/symfony/filesystem/zipball/7bf9162d7a0dff98d079b72948508fa48018a770",
"reference": "d937d400b980523dc9ee946bb69972b5e619058d", "reference": "7bf9162d7a0dff98d079b72948508fa48018a770",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2547,7 +2547,7 @@
"description": "Provides basic utilities for the filesystem", "description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/filesystem/tree/v8.0.1" "source": "https://github.com/symfony/filesystem/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -2567,20 +2567,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-12-01T09:13:36+00:00" "time": "2026-02-25T16:59:43+00:00"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v8.0.5", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
"reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0" "reference": "441404f09a54de6d1bd6ad219e088cdf4c91f97c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/8bd576e97c67d45941365bf824e18dc8538e6eb0", "url": "https://api.github.com/repos/symfony/finder/zipball/441404f09a54de6d1bd6ad219e088cdf4c91f97c",
"reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0", "reference": "441404f09a54de6d1bd6ad219e088cdf4c91f97c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2615,7 +2615,7 @@
"description": "Finds files and directories via an intuitive fluent interface", "description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/finder/tree/v8.0.5" "source": "https://github.com/symfony/finder/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -2635,20 +2635,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-26T15:08:38+00:00" "time": "2026-01-29T09:41:02+00:00"
}, },
{ {
"name": "symfony/framework-bundle", "name": "symfony/framework-bundle",
"version": "v8.0.5", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/framework-bundle.git", "url": "https://github.com/symfony/framework-bundle.git",
"reference": "e2f9469e7a802dd7c0d193792afc494d68177c54" "reference": "86ebd86908edca06e3af5994bc46881575fbe813"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/framework-bundle/zipball/e2f9469e7a802dd7c0d193792afc494d68177c54", "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/86ebd86908edca06e3af5994bc46881575fbe813",
"reference": "e2f9469e7a802dd7c0d193792afc494d68177c54", "reference": "86ebd86908edca06e3af5994bc46881575fbe813",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2671,7 +2671,7 @@
}, },
"conflict": { "conflict": {
"doctrine/persistence": "<1.3", "doctrine/persistence": "<1.3",
"phpdocumentor/reflection-docblock": "<5.2|>=6", "phpdocumentor/reflection-docblock": "<5.2|>=7",
"phpdocumentor/type-resolver": "<1.5.1", "phpdocumentor/type-resolver": "<1.5.1",
"symfony/console": "<7.4", "symfony/console": "<7.4",
"symfony/form": "<7.4", "symfony/form": "<7.4",
@@ -2686,7 +2686,7 @@
"require-dev": { "require-dev": {
"doctrine/persistence": "^1.3|^2|^3", "doctrine/persistence": "^1.3|^2|^3",
"dragonmantank/cron-expression": "^3.1", "dragonmantank/cron-expression": "^3.1",
"phpdocumentor/reflection-docblock": "^5.2", "phpdocumentor/reflection-docblock": "^5.2|^6.0",
"phpstan/phpdoc-parser": "^1.0|^2.0", "phpstan/phpdoc-parser": "^1.0|^2.0",
"seld/jsonlint": "^1.10", "seld/jsonlint": "^1.10",
"symfony/asset": "^7.4|^8.0", "symfony/asset": "^7.4|^8.0",
@@ -2755,7 +2755,7 @@
"description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/framework-bundle/tree/v8.0.5" "source": "https://github.com/symfony/framework-bundle/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -2775,20 +2775,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-27T09:06:10+00:00" "time": "2026-02-25T16:59:43+00:00"
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v8.0.5", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "e3422806e6f6760dbed0ddbc0a7fbfb6b5ce96bb" "reference": "7745ff1aad45d855fe25b08969269ef83b1ad8bc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/e3422806e6f6760dbed0ddbc0a7fbfb6b5ce96bb", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7745ff1aad45d855fe25b08969269ef83b1ad8bc",
"reference": "e3422806e6f6760dbed0ddbc0a7fbfb6b5ce96bb", "reference": "7745ff1aad45d855fe25b08969269ef83b1ad8bc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2835,7 +2835,7 @@
"description": "Defines an object-oriented layer for the HTTP specification", "description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-foundation/tree/v8.0.5" "source": "https://github.com/symfony/http-foundation/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -2855,20 +2855,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-27T16:18:07+00:00" "time": "2026-02-21T16:28:39+00:00"
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",
"version": "v8.0.5", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-kernel.git", "url": "https://github.com/symfony/http-kernel.git",
"reference": "20c1c5e41fc53928dbb670088f544f2d460d497d" "reference": "b567e571e74b5774b3d3cb4d35bdafa5f37e51a9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/20c1c5e41fc53928dbb670088f544f2d460d497d", "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b567e571e74b5774b3d3cb4d35bdafa5f37e51a9",
"reference": "20c1c5e41fc53928dbb670088f544f2d460d497d", "reference": "b567e571e74b5774b3d3cb4d35bdafa5f37e51a9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2939,7 +2939,7 @@
"description": "Provides a structured process for converting a Request into a Response", "description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-kernel/tree/v8.0.5" "source": "https://github.com/symfony/http-kernel/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -2959,20 +2959,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-28T10:46:31+00:00" "time": "2026-02-26T08:36:42+00:00"
}, },
{ {
"name": "symfony/intl", "name": "symfony/intl",
"version": "v8.0.4", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/intl.git", "url": "https://github.com/symfony/intl.git",
"reference": "8d049269c2accca0b02e5f9de39f3ee92ebc4468" "reference": "4e14323828f51a293edbce15ca98d4f3dd927cbf"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/intl/zipball/8d049269c2accca0b02e5f9de39f3ee92ebc4468", "url": "https://api.github.com/repos/symfony/intl/zipball/4e14323828f51a293edbce15ca98d4f3dd927cbf",
"reference": "8d049269c2accca0b02e5f9de39f3ee92ebc4468", "reference": "4e14323828f51a293edbce15ca98d4f3dd927cbf",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3028,7 +3028,7 @@
"localization" "localization"
], ],
"support": { "support": {
"source": "https://github.com/symfony/intl/tree/v8.0.4" "source": "https://github.com/symfony/intl/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -3048,7 +3048,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-12T12:37:40+00:00" "time": "2026-02-09T10:14:57+00:00"
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
@@ -3467,16 +3467,16 @@
}, },
{ {
"name": "symfony/routing", "name": "symfony/routing",
"version": "v8.0.4", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/routing.git", "url": "https://github.com/symfony/routing.git",
"reference": "4a2bc08d1c35307239329f434d45c2bfe8241fa9" "reference": "053c40fd46e1d19c5c5a94cada93ce6c3facdd55"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/4a2bc08d1c35307239329f434d45c2bfe8241fa9", "url": "https://api.github.com/repos/symfony/routing/zipball/053c40fd46e1d19c5c5a94cada93ce6c3facdd55",
"reference": "4a2bc08d1c35307239329f434d45c2bfe8241fa9", "reference": "053c40fd46e1d19c5c5a94cada93ce6c3facdd55",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3523,7 +3523,7 @@
"url" "url"
], ],
"support": { "support": {
"source": "https://github.com/symfony/routing/tree/v8.0.4" "source": "https://github.com/symfony/routing/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -3543,7 +3543,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-12T12:37:40+00:00" "time": "2026-02-25T16:59:43+00:00"
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",
@@ -3634,16 +3634,16 @@
}, },
{ {
"name": "symfony/string", "name": "symfony/string",
"version": "v8.0.4", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/string.git", "url": "https://github.com/symfony/string.git",
"reference": "758b372d6882506821ed666032e43020c4f57194" "reference": "6c9e1108041b5dce21a9a4984b531c4923aa9ec4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/758b372d6882506821ed666032e43020c4f57194", "url": "https://api.github.com/repos/symfony/string/zipball/6c9e1108041b5dce21a9a4984b531c4923aa9ec4",
"reference": "758b372d6882506821ed666032e43020c4f57194", "reference": "6c9e1108041b5dce21a9a4984b531c4923aa9ec4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3700,7 +3700,7 @@
"utf8" "utf8"
], ],
"support": { "support": {
"source": "https://github.com/symfony/string/tree/v8.0.4" "source": "https://github.com/symfony/string/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -3720,20 +3720,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-12T12:37:40+00:00" "time": "2026-02-09T10:14:57+00:00"
}, },
{ {
"name": "symfony/translation", "name": "symfony/translation",
"version": "v8.0.4", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/translation.git", "url": "https://github.com/symfony/translation.git",
"reference": "db70c8ce7db74fd2da7b1d268db46b2a8ce32c10" "reference": "13ff19bcf2bea492d3c2fbeaa194dd6f4599ce1b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/db70c8ce7db74fd2da7b1d268db46b2a8ce32c10", "url": "https://api.github.com/repos/symfony/translation/zipball/13ff19bcf2bea492d3c2fbeaa194dd6f4599ce1b",
"reference": "db70c8ce7db74fd2da7b1d268db46b2a8ce32c10", "reference": "13ff19bcf2bea492d3c2fbeaa194dd6f4599ce1b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3793,7 +3793,7 @@
"description": "Provides tools to internationalize your application", "description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/translation/tree/v8.0.4" "source": "https://github.com/symfony/translation/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -3813,7 +3813,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-13T13:06:50+00:00" "time": "2026-02-17T13:07:04+00:00"
}, },
{ {
"name": "symfony/translation-contracts", "name": "symfony/translation-contracts",
@@ -3899,16 +3899,16 @@
}, },
{ {
"name": "symfony/twig-bridge", "name": "symfony/twig-bridge",
"version": "v8.0.5", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/twig-bridge.git", "url": "https://github.com/symfony/twig-bridge.git",
"reference": "3e60c35cb47b1077524c066ec277eaf92cdc2393" "reference": "a29b174218f6eb324bf24f60440ac81d17f6ee0d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/twig-bridge/zipball/3e60c35cb47b1077524c066ec277eaf92cdc2393", "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/a29b174218f6eb324bf24f60440ac81d17f6ee0d",
"reference": "3e60c35cb47b1077524c066ec277eaf92cdc2393", "reference": "a29b174218f6eb324bf24f60440ac81d17f6ee0d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3917,14 +3917,14 @@
"twig/twig": "^3.21" "twig/twig": "^3.21"
}, },
"conflict": { "conflict": {
"phpdocumentor/reflection-docblock": "<5.2|>=6", "phpdocumentor/reflection-docblock": "<5.2|>=7",
"phpdocumentor/type-resolver": "<1.5.1", "phpdocumentor/type-resolver": "<1.5.1",
"symfony/form": "<7.4.4|>8.0,<8.0.4" "symfony/form": "<7.4.4|>8.0,<8.0.4"
}, },
"require-dev": { "require-dev": {
"egulias/email-validator": "^2.1.10|^3|^4", "egulias/email-validator": "^2.1.10|^3|^4",
"league/html-to-markdown": "^5.0", "league/html-to-markdown": "^5.0",
"phpdocumentor/reflection-docblock": "^5.2", "phpdocumentor/reflection-docblock": "^5.2|^6.0",
"symfony/asset": "^7.4|^8.0", "symfony/asset": "^7.4|^8.0",
"symfony/asset-mapper": "^7.4|^8.0", "symfony/asset-mapper": "^7.4|^8.0",
"symfony/console": "^7.4|^8.0", "symfony/console": "^7.4|^8.0",
@@ -3982,7 +3982,7 @@
"description": "Provides integration for Twig with various Symfony components", "description": "Provides integration for Twig with various Symfony components",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/twig-bridge/tree/v8.0.5" "source": "https://github.com/symfony/twig-bridge/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -4002,7 +4002,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-27T09:06:10+00:00" "time": "2026-02-25T16:59:43+00:00"
}, },
{ {
"name": "symfony/twig-bundle", "name": "symfony/twig-bundle",
@@ -4090,16 +4090,16 @@
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v8.0.4", "version": "v8.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "326e0406fc315eca57ef5740fa4a280b7a068c82" "reference": "2e14f7e0bf5ff02c6e63bd31cb8e4855a13d6209"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/326e0406fc315eca57ef5740fa4a280b7a068c82", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2e14f7e0bf5ff02c6e63bd31cb8e4855a13d6209",
"reference": "326e0406fc315eca57ef5740fa4a280b7a068c82", "reference": "2e14f7e0bf5ff02c6e63bd31cb8e4855a13d6209",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4153,7 +4153,7 @@
"dump" "dump"
], ],
"support": { "support": {
"source": "https://github.com/symfony/var-dumper/tree/v8.0.4" "source": "https://github.com/symfony/var-dumper/tree/v8.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -4173,7 +4173,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-01-01T23:07:29+00:00" "time": "2026-02-15T10:53:29+00:00"
}, },
{ {
"name": "symfony/var-exporter", "name": "symfony/var-exporter",

View File

@@ -118,6 +118,66 @@ class Migrate extends Command
] ]
); );
} }
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'Netherlands')->exists()) {
Capsule::table('countries')->insert([
'countryName' => 'Netherlands',
'productsUrl' => 'https://nl.ryobitools.eu/api/product-listing/get-products',
'cultureCode' => 'nl-NL',
'currency' => 'EUR',
'locale' => 'nl',
'created_at' => now(),
'updated_at' => now(),
]
);
}
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'France')->exists()) {
Capsule::table('countries')->insert([
'countryName' => 'France',
'productsUrl' => 'https://fr.ryobitools.eu/api/product-listing/get-products',
'cultureCode' => 'fr-FR',
'currency' => 'EUR',
'locale' => 'fr',
'created_at' => now(),
'updated_at' => now(),
]
);
}
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'Spain')->exists()) {
Capsule::table('countries')->insert([
'countryName' => 'Spain',
'productsUrl' => 'https://es.ryobitools.eu/api/product-listing/get-products',
'cultureCode' => 'es-ES',
'currency' => 'EUR',
'locale' => 'es',
'created_at' => now(),
'updated_at' => now(),
]
);
}
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'Poland')->exists()) {
$id = Capsule::table('countries')->insertGetId(
[
'countryName' => 'Poland',
'productsUrl' => 'https://pl.ryobitools.eu/api/product-listing/get-products',
'cultureCode' => 'pl-PL',
'currency' => 'PLN',
'locale' => 'pl',
'created_at' => now(),
'updated_at' => now(),
]);
}
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'UK')->exists()) {
Capsule::table('countries')->insert([
'countryName' => 'UK',
'productsUrl' => 'https://uk.ryobitools.eu/api/product-listing/get-products',
'cultureCode' => 'en-GB',
'currency' => 'GBP',
'locale' => 'uk',
'created_at' => now(),
'updated_at' => now(),
]
);
}
if (!Capsule::schema()->hasColumn('products', 'country_id')) { if (!Capsule::schema()->hasColumn('products', 'country_id')) {
Capsule::schema()->table('products', function (Blueprint $table) use ($id) { Capsule::schema()->table('products', function (Blueprint $table) use ($id) {

View File

@@ -76,6 +76,8 @@ class ScrapeWebsite extends Command
$output->writeln('Update prices - DONE'); $output->writeln('Update prices - DONE');
$output->writeln('COMMAND - DONE'); $output->writeln('COMMAND - DONE');
file_put_contents('templates/lastscrape.html.twig', date('Y-m-d H:i:s'));
return Command::SUCCESS; return Command::SUCCESS;
} }

View File

@@ -20,8 +20,11 @@ final class PromosController extends BaseController
$promos = Product::select($this->database->getConnection()->raw("distinct json_extract(promotions, '$.slug') as slug, json_extract(promotions, '$.tag') as tag")) $promos = Product::select($this->database->getConnection()->raw("distinct json_extract(promotions, '$.slug') as slug, json_extract(promotions, '$.tag') as tag"))
->addSelect('countries.locale')
->whereRaw("json_extract(promotions, '$.tag') is not null") ->whereRaw("json_extract(promotions, '$.tag') is not null")
->get(); ->join('countries', 'products.country_id', '=', 'countries.id')
->get()
->groupBy('locale');
return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'promos' . $promo, 'promos' => $promos->toArray()]); return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'promos' . $promo, 'promos' => $promos->toArray()]);
} }

View File

@@ -7,13 +7,9 @@ use Krzysiej\RyobiCrawler\Twig\AppExtension;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Bundle\TwigBundle\TwigBundle; use Symfony\Bundle\TwigBundle\TwigBundle;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\Kernel as BaseKernel; use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
use Twig\Extra\Cache\CacheExtension;
use Twig\Extra\Cache\CacheRuntime;
use Twig\Extra\TwigExtraBundle\TwigExtraBundle; use Twig\Extra\TwigExtraBundle\TwigExtraBundle;
class Kernel extends BaseKernel class Kernel extends BaseKernel

View File

@@ -0,0 +1,12 @@
<div class="container">
<footer class="d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
<div class="col-md-4 d-flex align-items-center">
<span class="mb-md-0 text-body-secondary">© 2025 Company, Inc</span>
<a class="align-items-center text-decoration-none" data-bs-theme-value="light">☀️ Light</a>
<a class="align-items-center text-decoration-none" data-bs-theme-value="dark">🌕 Dark</a>
</div>
<div class="col-md-4 text-end text-muted">
{{ include('lastscrape.html.twig', ignore_missing: true) }}
</div>
</footer>
</div>

View File

@@ -11,8 +11,7 @@
<td> <td>
<a href='{{ path('app_product', {'productId': product.id}) }}' <a href='{{ path('app_product', {'productId': product.id}) }}'
class="text-decoration-none">{{ product.name }}</a> class="text-decoration-none">{{ product.name }}</a>
<span class="badge text-bg-light"><a href="{{ path('app_search', {'search': product.subTitle}) }}" <a href="{{ path('app_search', {'search': product.subTitle}) }}"><span class="badge text-bg-secondary">{{ product.subTitle }}</span></a>
class="link-underline link-underline-opacity-0 link-dark">{{ product.subTitle }}</a></span>
{% if product.promotions is not null and product.promotions.hasPromotion %}<a {% if product.promotions is not null and product.promotions.hasPromotion %}<a
href="{{ path('app_promos', {'promo': product.promotions.slug}) }}"><span class="badge bg-info">PROMO: {{ product.promotions.tag }}</span> href="{{ path('app_promos', {'promo': product.promotions.slug}) }}"><span class="badge bg-info">PROMO: {{ product.promotions.tag }}</span>
</a>{% endif %} </a>{% endif %}

View File

@@ -6,9 +6,17 @@
{% endif %} {% endif %}
{% if listType starts with 'promos' %} {% if listType starts with 'promos' %}
{% for promo in promos %} <ul class="list-group list-group-flush">
<a href="{{ path('app_promos', {'promo': promo.slug}) }}"><span class="badge bg-info">PROMO: {{ promo.tag }}</span></a> {% for locale, promoByLocale in promos %}
{% endfor %} <li class="list-group-item">
<h5 class="d-inline-block"><span class="badge bg-info">{{ locale | upper }}</span></h5>
{% for promo in promoByLocale %}
<a href="{{ path('app_promos', {'promo': promo.slug}) }}"><span
class="badge bg-info">PROMO: {{ promo.tag }} [{{ promo.locale | upper }}]</span></a>
{% endfor %}
</li>
{% endfor %}
</ul>
{% endif %} {% endif %}
@@ -38,22 +46,21 @@
<td class="align-middle"> <td class="align-middle">
<a href='{{ path('app_product', {'productId': product.id}) }}' <a href='{{ path('app_product', {'productId': product.id}) }}'
class="text-decoration-none">{{ product.name }}</a> class="text-decoration-none">{{ product.name }}</a>
<br>
{% if product.stock > 0 %} {% if product.stock > 0 %}
<span class="badge text-bg-light">stock: {{ product.stock }}</span> <span class="badge text-bg-secondary">stock: {{ product.stock }}</span>
{% else %} {% else %}
<span class="badge text-bg-warning">out of stock</span> <span class="badge text-bg-warning">out of stock</span>
{% endif %} {% endif %}
{% if product.isDiscontinued() %} {% if product.isDiscontinued() %}
<span class="badge text-bg-secondary" data-bs-toggle="tooltip" <a href="{{ path('app_discontinued') }}"><span class="badge text-bg-secondary" data-bs-title="Last update: {{ product.lastSeen }}">is discontinued</span></a>
data-bs-title="Last update: {{ product.lastSeen }}">is discontinued</span>
{% endif %} {% endif %}
{% if product.isNew() %} {% if product.isNew() %}
<span class="badge text-bg-success">is new</span> <a href="{{ path('app_new') }}"><span class="badge text-bg-success">is new</span></a>
{% endif %} {% endif %}
<span class="badge text-bg-light"><a <a href="{{ path('app_search', {'search': product.subTitle}) }}"><span class="badge text-bg-secondary">{{ product.subTitle }}</span></a>
href="{{ path('app_search', {'search': product.subTitle}) }}"
class="link-underline link-underline-opacity-0 link-dark">{{ product.subTitle }}</a></span>
{% if product.promotions is not null and product.promotions.hasPromotion %}<a href="{{ path('app_promos', {'promo': product.promotions.slug}) }}"><span class="badge bg-info">PROMO: {{ product.promotions.tag }}</span></a>{% endif %} {% if product.promotions is not null and product.promotions.hasPromotion %}<a href="{{ path('app_promos', {'promo': product.promotions.slug}) }}"><span class="badge bg-info">PROMO: {{ product.promotions.tag }}</span></a>{% endif %}
<span class="badge text-bg-secondary">{{ product.country.countryName }}</span>
</td> </td>
<td class="align-middle"> <td class="align-middle">
<nav aria-label="breadcrumb" style="--bs-breadcrumb-divider: '>';"> <nav aria-label="breadcrumb" style="--bs-breadcrumb-divider: '>';">

View File

@@ -1,6 +1,75 @@
<!doctype html> <!doctype html>
<html lang="en" data-bs-theme="light"> <html lang="en" data-bs-theme="">
<head> <head>
<script>
(() => {
'use strict'
const getStoredTheme = () => localStorage.getItem('theme')
const setStoredTheme = theme => localStorage.setItem('theme', theme)
const getPreferredTheme = () => {
const storedTheme = getStoredTheme()
if (storedTheme) {
return storedTheme
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
const setTheme = theme => {
if (theme === 'auto') {
document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'))
} else {
document.documentElement.setAttribute('data-bs-theme', theme)
}
}
setTheme(getPreferredTheme())
const showActiveTheme = (theme, focus = false) => {
const themeSwitcher = document.querySelector('#bd-theme')
if (!themeSwitcher) {
return
}
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
element.classList.remove('active')
})
btnToActive.classList.add('active')
if (focus) {
themeSwitcher.focus()
}
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
const storedTheme = getStoredTheme()
if (storedTheme !== 'light' && storedTheme !== 'dark') {
setTheme(getPreferredTheme())
}
})
window.addEventListener('DOMContentLoaded', () => {
showActiveTheme(getPreferredTheme())
document.querySelectorAll('[data-bs-theme-value]')
.forEach(toggle => {
toggle.addEventListener('click', () => {
const theme = toggle.getAttribute('data-bs-theme-value')
setStoredTheme(theme)
setTheme(theme)
showActiveTheme(theme, true)
})
})
})
})()
</script>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
@@ -13,7 +82,8 @@
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="{{ path('app_home') }}">Crawler</a> <a class="navbar-brand" href="{{ path('app_home') }}">Crawler</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<div class="collapse navbar-collapse" id="navbarNav"> <div class="collapse navbar-collapse" id="navbarNav">
@@ -45,6 +115,7 @@
</nav> </nav>
{% block content %}{% endblock %} {% block content %}{% endblock %}
{{ include('footer.html.twig') }}
<script src="/templates/js/bootstrap.bundle.min.js"></script> <script src="/templates/js/bootstrap.bundle.min.js"></script>
</body> </body>
</html> </html>