generated from boboko/starter
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac888f91e3 |
@@ -72,8 +72,6 @@ AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
|
||||
SESSION_SECURE_COOKIE=true
|
||||
|
||||
# Stoic is the headless CMS, proxied at /stoic/ behind the app in prod (see docker/nginx/prod.conf)
|
||||
STOIC_SECRET=dev-secret-change-me
|
||||
STOIC_SSO_SECRET=dev-sso-secret-change-me
|
||||
|
||||
@@ -44,11 +44,7 @@ public function show(string $locale, Request $request, int $orderId): View
|
||||
return view('account.orders.show', [
|
||||
'order' => $order,
|
||||
'paymentMethodName' => $paymentMethodName,
|
||||
// Active shipments with a number; return vouchers are the shop's
|
||||
// business, not the customer's.
|
||||
'shipments' => $order->shipments
|
||||
->reject(fn ($shipment) => $shipment->isCancelled() || $shipment->isReturn() || blank($shipment->tracking_reference))
|
||||
->values(),
|
||||
'shipments' => $order->shipments->whereNull('cancelled_at')->whereNotNull('tracking_reference'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-13
@@ -29,26 +29,16 @@ class User extends Authenticatable implements LunarUserInterface
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for serialization. Every
|
||||
* secret-bearing OTP/pending-email-change field is included here,
|
||||
* not just remember_token — otp_code_hash and
|
||||
* pending_email_code_hash are bcrypt hashes rather than the raw
|
||||
* codes (see Modules\Core\Auth\Services\UserOtpService and
|
||||
* Modules\Core\Customer\Services\CustomerEmailChangeService), but a
|
||||
* hash is still not something any serialized response should leak,
|
||||
* and otp_attempts/pending_email_attempts reveal in-progress guess
|
||||
* counts.
|
||||
* The attributes that should be hidden for serialization.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'remember_token',
|
||||
'otp_code_hash',
|
||||
'otp_code',
|
||||
'otp_expires_at',
|
||||
'otp_attempts',
|
||||
'pending_email_code_hash',
|
||||
'pending_email_expires_at',
|
||||
'pending_email_attempts',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -60,7 +50,6 @@ protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'email_verified_at' => 'datetime',
|
||||
'otp_code_hash' => 'hashed',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
-146
@@ -1,146 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Switch how this app consumes boboko-core, then restart the dev stack so the
|
||||
# entrypoints re-resolve it.
|
||||
#
|
||||
# bin/core-mode local ../boboko-core checkout (Composer path repo + npm file:)
|
||||
# bin/core-mode repo tagged releases from the forge (Composer VCS repo + npm git+semver)
|
||||
# bin/core-mode print the current mode
|
||||
#
|
||||
# Running it for the mode you're already in skips the file edits but still
|
||||
# restarts the stack — that's how repo mode picks up a newly pushed tag.
|
||||
#
|
||||
# The toggle lives in composer.json ("repositories" <-> "_repositories") and
|
||||
# package.json (@boboko/core in "dependencies" <-> "_dependencies"). The dev
|
||||
# entrypoints run `composer update boboko/*` and `npm update @boboko/core` on
|
||||
# every boot, which rewrites composer.lock / package-lock.json for the mode.
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
fail() { echo "!!! $*" >&2; exit 1; }
|
||||
|
||||
# Escape a string for use as a sed regex / replacement with "|" as delimiter.
|
||||
sed_pattern() { printf '%s' "$1" | sed 's/[][\.*^$|]/\\&/g'; }
|
||||
sed_replacement() { printf '%s' "$1" | sed 's/[\&|]/\\&/g'; }
|
||||
|
||||
current_mode() {
|
||||
local composer_type npm_dep composer_mode npm_mode
|
||||
# The live block is "repositories" — the leading quote keeps "_repositories" out.
|
||||
composer_type=$(sed -n '/"repositories": \[/,/"type"/p' composer.json | grep -o '"type": "[a-z]*"' | head -1)
|
||||
npm_dep=$(sed -n '/"dependencies": {/,/}/p' package.json | grep -o '"@boboko/core": "[^"]*"' | head -1)
|
||||
|
||||
case "$composer_type" in
|
||||
*'"path"') composer_mode=local ;;
|
||||
*'"vcs"') composer_mode=repo ;;
|
||||
*) fail "Can't tell the mode from composer.json's \"repositories\" block." ;;
|
||||
esac
|
||||
case "$npm_dep" in
|
||||
*'"file:'*) npm_mode=local ;;
|
||||
*'"git+'*) npm_mode=repo ;;
|
||||
*) fail "Can't tell the mode from package.json's @boboko/core dependency." ;;
|
||||
esac
|
||||
[ "$composer_mode" = "$npm_mode" ] ||
|
||||
fail "composer.json ($composer_mode) and package.json ($npm_mode) disagree — fix by hand first."
|
||||
|
||||
echo "$composer_mode"
|
||||
}
|
||||
|
||||
swap_files() {
|
||||
# composer.json: swap the key names, values stay where they are.
|
||||
sed -i \
|
||||
-e 's/"_repositories":/"__core_mode_swap__":/' \
|
||||
-e 's/"repositories":/"_repositories":/' \
|
||||
-e 's/"__core_mode_swap__":/"repositories":/' \
|
||||
composer.json
|
||||
|
||||
# package.json: swap the two @boboko/core values (live and parked).
|
||||
local a b
|
||||
a=$(grep -o '"@boboko/core": "[^"]*"' package.json | sed -n 1p)
|
||||
b=$(grep -o '"@boboko/core": "[^"]*"' package.json | sed -n 2p)
|
||||
[ -n "$a" ] && [ -n "$b" ] || fail "Expected two @boboko/core entries in package.json."
|
||||
sed -i \
|
||||
-e "s|$(sed_pattern "$a")|__core_mode_swap__|" \
|
||||
-e "s|$(sed_pattern "$b")|$(sed_replacement "$a")|" \
|
||||
-e "s|__core_mode_swap__|$(sed_replacement "$b")|" \
|
||||
package.json
|
||||
}
|
||||
|
||||
wrapper_for() {
|
||||
if [ "$1" = local ]; then echo bin/dc-core.sh; else echo bin/dc; fi
|
||||
}
|
||||
|
||||
# The app healthcheck (php-fpm -t) passes before the entrypoint finishes, so
|
||||
# wait on the entrypoints' own log lines instead: the app's composer block is
|
||||
# done once it clears caches, the vite container's npm block once Vite is up.
|
||||
wait_for_log() {
|
||||
local dc=$1 service=$2 pattern=$3 label=$4 waited=0
|
||||
printf '>>> Waiting for %s' "$label"
|
||||
until $dc logs --no-color "$service" 2>&1 | grep -q "$pattern"; do
|
||||
if [ -z "$($dc ps -q --status running "$service")" ]; then
|
||||
echo
|
||||
$dc logs --no-color --tail 40 "$service"
|
||||
fail "$service stopped before finishing (logs above)."
|
||||
fi
|
||||
if [ "$waited" -ge 600 ]; then
|
||||
echo
|
||||
$dc logs --no-color --tail 40 "$service"
|
||||
fail "Timed out after 600s waiting for $service (logs above)."
|
||||
fi
|
||||
printf '.'
|
||||
sleep 3
|
||||
waited=$((waited + 3))
|
||||
done
|
||||
echo " done"
|
||||
}
|
||||
|
||||
mode=$(current_mode)
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "$mode"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
target=$1
|
||||
[ "$target" = local ] || [ "$target" = repo ] || fail "Usage: bin/core-mode [local|repo]"
|
||||
if [ "$target" = local ] && [ ! -d ../boboko-core ]; then
|
||||
fail "../boboko-core not found — local mode needs the core checkout next to this repo."
|
||||
fi
|
||||
|
||||
old_dc=$(wrapper_for "$mode")
|
||||
new_dc=$(wrapper_for "$target")
|
||||
|
||||
echo ">>> Stopping stack ($mode mode)..."
|
||||
$old_dc down
|
||||
|
||||
if [ "$mode" != "$target" ]; then
|
||||
echo ">>> Switching composer.json / package.json: $mode -> $target"
|
||||
swap_files
|
||||
[ "$(current_mode)" = "$target" ] || fail "Switch didn't take — check composer.json / package.json."
|
||||
else
|
||||
echo ">>> Already in $target mode, restarting to re-resolve boboko-core"
|
||||
fi
|
||||
|
||||
# The entrypoints run `composer install` / `npm install` from the lockfiles
|
||||
# BEFORE re-resolving core. Local-mode lockfiles point at ../boboko-core,
|
||||
# which isn't mounted in repo mode, so the install fails. The committed
|
||||
# lockfiles are always repo mode — restore those and let the entrypoints bump
|
||||
# them to the newest tag.
|
||||
if [ "$target" = repo ]; then
|
||||
if grep -A14 '"name": "boboko/core"' composer.lock | grep -q '"type": "path"' ||
|
||||
grep -A6 '"node_modules/@boboko/core": {' package-lock.json | grep -q '"link": true'; then
|
||||
echo ">>> Lockfiles still point at ../boboko-core — restoring the committed ones"
|
||||
git checkout HEAD -- composer.lock package-lock.json
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ">>> Starting stack ($target mode)..."
|
||||
if ! $new_dc up -d; then
|
||||
$new_dc logs --no-color --tail 40 app
|
||||
fail "Stack failed to start (app logs above)."
|
||||
fi
|
||||
|
||||
wait_for_log "$new_dc" app '\[entrypoint\] Caches cleared' "composer to re-resolve boboko/core"
|
||||
wait_for_log "$new_dc" vite 'ready in' "npm to re-resolve @boboko/core"
|
||||
|
||||
version=$(grep -A1 '"name": "boboko/core"' composer.lock | grep -o '"version": "[^"]*"' | cut -d'"' -f4)
|
||||
echo ">>> Now in $target mode — boboko/core $version"
|
||||
-120
@@ -1,120 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy this app to production with the latest boboko-core tag.
|
||||
#
|
||||
# 1. Refuses to run with uncommitted work (the server deploys what's pushed,
|
||||
# nothing else) — only the core wiring files are allowed to be dirty.
|
||||
# 2. Pulls translation lines added in the Language Lines UI into core's
|
||||
# seeders (boboko:translations:pull) — in local mode; if any are pulled,
|
||||
# stops so you can release core first. In repo mode it only checks.
|
||||
# 3. Switches to repo mode if you're on the local ../boboko-core checkout,
|
||||
# and restarts the stack either way so the lockfiles pick up the newest
|
||||
# tag (bin/core-mode repo).
|
||||
# 4. Commits the lockfile bump, if any, asks for confirmation, pushes.
|
||||
# 5. Runs `envoy run deploy` (see Envoy.blade.php) against .env.envoy's host.
|
||||
#
|
||||
# Leaves you in repo mode — run `bin/core-mode local` to go back.
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
fail() { echo "!!! $*" >&2; exit 1; }
|
||||
|
||||
[ -f .env.envoy ] || fail ".env.envoy not found — copy .env.envoy.example and fill it in."
|
||||
branch=$(grep -m1 '^DEPLOY_BRANCH=' .env.envoy | cut -d= -f2-)
|
||||
host=$(grep -m1 '^DEPLOY_SSH_HOST=' .env.envoy | cut -d= -f2-)
|
||||
branch=${branch:-master}
|
||||
|
||||
[ "$(git branch --show-current)" = "$branch" ] || fail "You're not on $branch (the branch Envoy deploys)."
|
||||
|
||||
# Anything tracked and modified other than the four core wiring files would be
|
||||
# silently left out of the deploy — make that a hard stop instead.
|
||||
dirty=$(git status --porcelain --untracked-files=no |
|
||||
grep -vE '^.. (composer\.json|composer\.lock|package\.json|package-lock\.json)$' || true)
|
||||
if [ -n "$dirty" ]; then
|
||||
echo "$dirty"
|
||||
fail "Commit or stash these first — the server only deploys what's pushed."
|
||||
fi
|
||||
|
||||
echo ">>> Fetching origin..."
|
||||
git fetch origin "$branch"
|
||||
[ "$(git rev-list --count "HEAD..origin/$branch")" -eq 0 ] || fail "origin/$branch has commits you don't — pull first."
|
||||
|
||||
# Translation lines added through the Language Lines UI only reach other apps
|
||||
# once they're in core's seeders. In local mode, pull them into
|
||||
# ../boboko-core; in repo mode the command can only report them.
|
||||
lines_in() { printf '%s\n' "$1" | sed -n 's/^\([0-9][0-9]*\) line(s).*/\1/p' | tail -1; }
|
||||
|
||||
if [ "$(bin/core-mode)" = local ]; then
|
||||
echo ">>> Pulling UI-added translations into ../boboko-core's seeders..."
|
||||
out=$(bin/dc-core.sh exec -T app php artisan boboko:translations:pull --no-ansi) ||
|
||||
fail "boboko:translations:pull failed — is the stack running (bin/dc-core.sh up -d)?"
|
||||
echo "$out"
|
||||
pulled=$(lines_in "$out")
|
||||
if [ "${pulled:-0}" -gt 0 ]; then
|
||||
fail "Pulled $pulled translation line(s) into ../boboko-core. Review, commit, tag and push core, then rerun bin/deploy."
|
||||
fi
|
||||
else
|
||||
echo ">>> Checking for UI-added translations missing from core's seeders..."
|
||||
if out=$(bin/dc exec -T app php artisan boboko:translations:pull --dry-run --no-ansi 2>&1); then
|
||||
missing=$(lines_in "$out")
|
||||
if [ "${missing:-0}" -gt 0 ]; then
|
||||
echo "$out"
|
||||
fail "These lines are only in this database — run bin/core-mode local and rerun bin/deploy to pull them into core."
|
||||
fi
|
||||
echo " nothing missing"
|
||||
else
|
||||
echo " skipped — the installed boboko/core doesn't have boboko:translations:pull yet"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Switch to repo mode (or just restart if already there) so both lockfiles
|
||||
# resolve the newest boboko-core tag.
|
||||
bin/core-mode repo
|
||||
|
||||
git diff --quiet HEAD -- composer.json package.json ||
|
||||
fail "composer.json / package.json differ from HEAD in repo mode — they should only differ by the local/repo toggle."
|
||||
if grep -A14 '"name": "boboko/core"' composer.lock | grep -q '"type": "path"'; then
|
||||
fail "composer.lock still points boboko/core at the local path repo."
|
||||
fi
|
||||
if grep -A6 '"node_modules/@boboko/core": {' package-lock.json | grep -q '"link": true'; then
|
||||
fail "package-lock.json still links @boboko/core to the local checkout."
|
||||
fi
|
||||
|
||||
version=$(grep -A1 '"name": "boboko/core"' composer.lock | grep -o '"version": "[^"]*"' | cut -d'"' -f4)
|
||||
|
||||
# A tag you created in ../boboko-core but never pushed won't be resolved.
|
||||
if [ -d ../boboko-core ]; then
|
||||
latest=$(git -C ../boboko-core tag --sort=-v:refname | head -1)
|
||||
if [ -n "$latest" ] && [ "$latest" != "v$version" ]; then
|
||||
echo "!!! Warning: resolved boboko/core $version, but ../boboko-core's newest tag is $latest."
|
||||
echo "!!! Did you push it? (git -C ../boboko-core push origin $latest)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! git diff --quiet HEAD -- composer.lock package-lock.json; then
|
||||
echo ">>> Committing lockfiles for boboko/core $version..."
|
||||
git add composer.lock package-lock.json
|
||||
git commit -m "Chore: Bumping boboko/core to $version"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo ">>> Deploying $branch to $host with boboko/core $version."
|
||||
pending=$(git log --oneline "origin/$branch..HEAD")
|
||||
if [ -n "$pending" ]; then
|
||||
echo ">>> Commits to push:"
|
||||
echo "$pending"
|
||||
else
|
||||
echo ">>> Nothing new to push — this redeploys origin/$branch as-is."
|
||||
fi
|
||||
echo
|
||||
read -r -p "Push and deploy? [y/N] " answer
|
||||
[ "$answer" = y ] || [ "$answer" = Y ] || fail "Aborted."
|
||||
|
||||
if [ -n "$pending" ]; then
|
||||
git push origin "$branch"
|
||||
fi
|
||||
|
||||
vendor/bin/envoy run deploy
|
||||
|
||||
echo
|
||||
echo ">>> Done. You're in repo mode — run bin/core-mode local to go back to your ../boboko-core checkout."
|
||||
+16
-24
@@ -6,23 +6,11 @@
|
||||
|
||||
return Application::configure(basePath: dirname(__DIR__))
|
||||
->withRouting(
|
||||
web: __DIR__ . '/../routes/web.php',
|
||||
commands: __DIR__ . '/../routes/console.php',
|
||||
web: __DIR__.'/../routes/web.php',
|
||||
commands: __DIR__.'/../routes/console.php',
|
||||
health: '/up',
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware): void {
|
||||
// nginx (docker/nginx/prod.conf) only listens on plain HTTP:80.
|
||||
// Without trusting that layer's X-Forwarded-Proto header, Laravel sees every
|
||||
// request as http://, so url()/signed-route generation and
|
||||
// verification (URL::hasValidSignature()) both use the wrong
|
||||
// scheme — breaks any signed URL whose recipient hits it over
|
||||
// https (e.g. Modules\Core\Shipping\Http\Controllers\
|
||||
// DownloadShipmentLabelController's label links) with a 401.
|
||||
// '*' trusts whatever's immediately upstream, since that's
|
||||
// container-to-container inside the same deploy, not arbitrary
|
||||
// public traffic.
|
||||
$middleware->trustProxies(at: '*');
|
||||
|
||||
// Laravel's priority list would otherwise run `auth` before core's
|
||||
// `locale` middleware, so the redirects below would build URLs before
|
||||
// URL::defaults(['locale' => …]) is set, throwing a missing-parameter error.
|
||||
@@ -33,17 +21,21 @@
|
||||
|
||||
// Both resolve inside the {locale} group, after the `locale` middleware
|
||||
// has set URL::defaults(['locale' => …]), so route() needs no locale arg.
|
||||
$middleware->redirectGuestsTo(fn() => route('login'));
|
||||
$middleware->redirectUsersTo(fn() => route('home'));
|
||||
$middleware->redirectGuestsTo(fn () => route('login'));
|
||||
$middleware->redirectUsersTo(fn () => route('home'));
|
||||
|
||||
// Core's session registry (Modules\Core\Auth\Services\
|
||||
// UserSessionService) is enforcement-optional by design — see
|
||||
// EnsureSessionNotRevoked's own docblock — and this app never
|
||||
// wired it in. Without this, revokeAllSessions() only flips a DB
|
||||
// flag that nothing checks per-request: a leaked/stolen session
|
||||
// cookie keeps working even after being "revoked". Appended to
|
||||
// `web` (runs after `auth` resolves the user, which it needs).
|
||||
$middleware->appendToGroup('web', \Modules\Core\Auth\Http\Middleware\EnsureSessionNotRevoked::class);
|
||||
// In production, the host's reverse proxy talks to the nginx container
|
||||
// (bound to 127.0.0.1 only), so without this every visitor has the
|
||||
// proxy's IP: the per-IP `throttle` limits on login become one shared
|
||||
// bucket for the whole site. '*' trusts only the direct hop.
|
||||
$middleware->trustProxies(at: '*');
|
||||
|
||||
// Enforces core's session registry: a session revoked via
|
||||
// UserSessionService is logged out on its next request. Core leaves
|
||||
// registering this to the app.
|
||||
$middleware->web(append: [
|
||||
\Modules\Core\Auth\Http\Middleware\EnsureSessionNotRevoked::class,
|
||||
]);
|
||||
})
|
||||
->withExceptions(function (Exceptions $exceptions): void {
|
||||
//
|
||||
|
||||
Generated
+134
-216
@@ -515,14 +515,13 @@
|
||||
},
|
||||
{
|
||||
"name": "boboko/core",
|
||||
"version": "0.31.0",
|
||||
"version": "0.27.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://code.radical-elements.com/boboko/core.git",
|
||||
"reference": "207cb133634feddb28efc9675726307ab99df205"
|
||||
"reference": "332bf92e4429cf5b787e106b9e8613d912dfcc4a"
|
||||
},
|
||||
"require": {
|
||||
"barryvdh/laravel-dompdf": "^3.1",
|
||||
"laravel/framework": "^12.0",
|
||||
"laravel/tinker": "^3.0",
|
||||
"lunarphp/lunar": "1.5.0",
|
||||
@@ -530,7 +529,6 @@
|
||||
"lunarphp/search": "*",
|
||||
"lunarphp/table-rate-shipping": "1.5.0",
|
||||
"php": "^8.5",
|
||||
"picqer/php-barcode-generator": "^3.3",
|
||||
"spatie/laravel-translation-loader": "^2.8",
|
||||
"stripe/stripe-php": "^16.6",
|
||||
"symfony/yaml": "^7.0"
|
||||
@@ -575,7 +573,7 @@
|
||||
}
|
||||
},
|
||||
"description": "Core module — authentication and shared panel behaviour",
|
||||
"time": "2026-09-30T22:51:41+00:00"
|
||||
"time": "2026-09-29T11:53:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
@@ -3113,16 +3111,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v12.69.3",
|
||||
"version": "v12.69.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "58ea544a2a80dc03c168e13a5dc9a1d176a88717"
|
||||
"reference": "17d034ef1e209b63a1d3a89c90ce5e89a4eb3fc5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/58ea544a2a80dc03c168e13a5dc9a1d176a88717",
|
||||
"reference": "58ea544a2a80dc03c168e13a5dc9a1d176a88717",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/17d034ef1e209b63a1d3a89c90ce5e89a4eb3fc5",
|
||||
"reference": "17d034ef1e209b63a1d3a89c90ce5e89a4eb3fc5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3331,7 +3329,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2026-09-29T12:53:25+00:00"
|
||||
"time": "2026-09-08T14:29:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
@@ -5158,16 +5156,16 @@
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "3.12.1",
|
||||
"version": "3.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Seldaek/monolog.git",
|
||||
"reference": "d7059e4c691d05ea1222b5124bed0f961be46e15"
|
||||
"reference": "72c534fc0ab181ef52d92a68382318631e301608"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/d7059e4c691d05ea1222b5124bed0f961be46e15",
|
||||
"reference": "d7059e4c691d05ea1222b5124bed0f961be46e15",
|
||||
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/72c534fc0ab181ef52d92a68382318631e301608",
|
||||
"reference": "72c534fc0ab181ef52d92a68382318631e301608",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5247,7 +5245,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Seldaek/monolog/issues",
|
||||
"source": "https://github.com/Seldaek/monolog/tree/3.12.1"
|
||||
"source": "https://github.com/Seldaek/monolog/tree/3.12.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5259,7 +5257,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-29T19:21:12+00:00"
|
||||
"time": "2026-09-09T08:34:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
@@ -6668,86 +6666,6 @@
|
||||
},
|
||||
"time": "2026-09-27T20:07:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "picqer/php-barcode-generator",
|
||||
"version": "v3.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/picqer/php-barcode-generator.git",
|
||||
"reference": "6beada2a30623832ff41b8c7d307c169736b8552"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/picqer/php-barcode-generator/zipball/6beada2a30623832ff41b8c7d307c169736b8552",
|
||||
"reference": "6beada2a30623832ff41b8c7d307c169736b8552",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "Barcode IMB (Intelligent Mail Barcode) needs bcmath extension",
|
||||
"ext-gd": "For JPG and PNG generators, GD or Imagick is required",
|
||||
"ext-imagick": "For JPG and PNG generators, GD or Imagick is required"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Picqer\\Barcode\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Casper Bakker",
|
||||
"email": "info@picqer.com",
|
||||
"homepage": "https://picqer.com"
|
||||
},
|
||||
{
|
||||
"name": "Nicola Asuni",
|
||||
"email": "info@tecnick.com",
|
||||
"homepage": "http://nicolaasuni.tecnick.com"
|
||||
}
|
||||
],
|
||||
"description": "An easy to use, non-bloated, barcode generator in PHP. Creates SVG, PNG, JPG and HTML images from the most used 1D barcode standards.",
|
||||
"homepage": "https://github.com/picqer/php-barcode-generator",
|
||||
"keywords": [
|
||||
"CODABAR",
|
||||
"Code11",
|
||||
"Code93",
|
||||
"EAN13",
|
||||
"KIX",
|
||||
"KIXCODE",
|
||||
"MSI",
|
||||
"POSTNET",
|
||||
"Pharma",
|
||||
"Standard 2 of 5",
|
||||
"barcode",
|
||||
"barcode generator",
|
||||
"code128",
|
||||
"code39",
|
||||
"ean",
|
||||
"html",
|
||||
"jpeg",
|
||||
"jpg",
|
||||
"php",
|
||||
"png",
|
||||
"svg",
|
||||
"upc"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/picqer/php-barcode-generator/issues",
|
||||
"source": "https://github.com/picqer/php-barcode-generator/tree/v3.3.0"
|
||||
},
|
||||
"time": "2026-08-22T09:50:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pragmarx/google2fa",
|
||||
"version": "v9.1.0",
|
||||
@@ -7947,16 +7865,16 @@
|
||||
},
|
||||
{
|
||||
"name": "spatie/image",
|
||||
"version": "3.9.7",
|
||||
"version": "3.9.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/image.git",
|
||||
"reference": "5450a2f63f315d56453fbbf58f5dacaecbf48dd4"
|
||||
"reference": "f6f2c785fb6e2f27cf05e48d6fe0e3feea0b421f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/image/zipball/5450a2f63f315d56453fbbf58f5dacaecbf48dd4",
|
||||
"reference": "5450a2f63f315d56453fbbf58f5dacaecbf48dd4",
|
||||
"url": "https://api.github.com/repos/spatie/image/zipball/f6f2c785fb6e2f27cf05e48d6fe0e3feea0b421f",
|
||||
"reference": "f6f2c785fb6e2f27cf05e48d6fe0e3feea0b421f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -8006,7 +7924,7 @@
|
||||
"spatie"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/spatie/image/tree/3.9.7"
|
||||
"source": "https://github.com/spatie/image/tree/3.9.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -8018,7 +7936,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-30T07:06:27+00:00"
|
||||
"time": "2026-08-18T08:48:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/image-optimizer",
|
||||
@@ -9325,16 +9243,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v7.4.20",
|
||||
"version": "v7.4.19",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d"
|
||||
"reference": "3a1973458b153f566a8d7499bc06ece323d60063"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d",
|
||||
"reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/3a1973458b153f566a8d7499bc06ece323d60063",
|
||||
"reference": "3a1973458b153f566a8d7499bc06ece323d60063",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -9399,7 +9317,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v7.4.20"
|
||||
"source": "https://github.com/symfony/console/tree/v7.4.19"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -9419,7 +9337,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-18T15:55:00+00:00"
|
||||
"time": "2026-09-13T10:38:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
@@ -9633,16 +9551,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/error-handler",
|
||||
"version": "v7.4.20",
|
||||
"version": "v7.4.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/error-handler.git",
|
||||
"reference": "82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0"
|
||||
"reference": "8373921e231e190a88e2ad526951bbaa791576fa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/error-handler/zipball/82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0",
|
||||
"reference": "82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0",
|
||||
"url": "https://api.github.com/repos/symfony/error-handler/zipball/8373921e231e190a88e2ad526951bbaa791576fa",
|
||||
"reference": "8373921e231e190a88e2ad526951bbaa791576fa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -9691,7 +9609,7 @@
|
||||
"description": "Provides tools to manage errors and ease debugging PHP code",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/error-handler/tree/v7.4.20"
|
||||
"source": "https://github.com/symfony/error-handler/tree/v7.4.17"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -9711,7 +9629,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-22T18:56:40+00:00"
|
||||
"time": "2026-08-21T17:40:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
@@ -9881,16 +9799,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v7.4.20",
|
||||
"version": "v7.4.19",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e"
|
||||
"reference": "1b900bc6ae5ba60c5eee69c11ba44566190576fe"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e",
|
||||
"reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/1b900bc6ae5ba60c5eee69c11ba44566190576fe",
|
||||
"reference": "1b900bc6ae5ba60c5eee69c11ba44566190576fe",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -9925,7 +9843,7 @@
|
||||
"description": "Finds files and directories via an intuitive fluent interface",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/finder/tree/v7.4.20"
|
||||
"source": "https://github.com/symfony/finder/tree/v7.4.19"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -9945,20 +9863,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-26T06:31:10+00:00"
|
||||
"time": "2026-09-10T19:14:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/html-sanitizer",
|
||||
"version": "v8.1.8",
|
||||
"version": "v8.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/html-sanitizer.git",
|
||||
"reference": "c67061a71d3f8b55f899faee3167422efa4db027"
|
||||
"reference": "3d79bdecd01f71bccc45ddfa1d33c024df347a1f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/c67061a71d3f8b55f899faee3167422efa4db027",
|
||||
"reference": "c67061a71d3f8b55f899faee3167422efa4db027",
|
||||
"url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/3d79bdecd01f71bccc45ddfa1d33c024df347a1f",
|
||||
"reference": "3d79bdecd01f71bccc45ddfa1d33c024df347a1f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -9997,7 +9915,7 @@
|
||||
"sanitizer"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/html-sanitizer/tree/v8.1.8"
|
||||
"source": "https://github.com/symfony/html-sanitizer/tree/v8.1.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10017,20 +9935,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-28T08:00:04+00:00"
|
||||
"time": "2026-09-04T10:14:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-foundation",
|
||||
"version": "v7.4.20",
|
||||
"version": "v7.4.19",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-foundation.git",
|
||||
"reference": "9d0761c0da6bd5b801b401666834901a9a1ffc33"
|
||||
"reference": "f7b953be7801974a5a0685e1228bbc3b12b35936"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/9d0761c0da6bd5b801b401666834901a9a1ffc33",
|
||||
"reference": "9d0761c0da6bd5b801b401666834901a9a1ffc33",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/f7b953be7801974a5a0685e1228bbc3b12b35936",
|
||||
"reference": "f7b953be7801974a5a0685e1228bbc3b12b35936",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10079,7 +9997,7 @@
|
||||
"description": "Defines an object-oriented layer for the HTTP specification",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v7.4.20"
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v7.4.19"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10099,20 +10017,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-24T07:12:44+00:00"
|
||||
"time": "2026-09-14T17:41:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-kernel",
|
||||
"version": "v7.4.20",
|
||||
"version": "v7.4.19",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-kernel.git",
|
||||
"reference": "392784b5d7b959b8d872542a2530c50c540a788f"
|
||||
"reference": "683507424cc84ca85ac1551adb609b6b98216667"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/392784b5d7b959b8d872542a2530c50c540a788f",
|
||||
"reference": "392784b5d7b959b8d872542a2530c50c540a788f",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/683507424cc84ca85ac1551adb609b6b98216667",
|
||||
"reference": "683507424cc84ca85ac1551adb609b6b98216667",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10198,7 +10116,7 @@
|
||||
"description": "Provides a structured process for converting a Request into a Response",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v7.4.20"
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v7.4.19"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10218,7 +10136,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-29T14:05:16+00:00"
|
||||
"time": "2026-09-15T07:09:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mailer",
|
||||
@@ -10549,16 +10467,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.43.0",
|
||||
"version": "v1.41.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||
"reference": "5cac8f4db97208823aa353f59a01faad2da52c75"
|
||||
"reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5cac8f4db97208823aa353f59a01faad2da52c75",
|
||||
"reference": "5cac8f4db97208823aa353f59a01faad2da52c75",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d",
|
||||
"reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10607,7 +10525,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.43.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10627,20 +10545,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-25T15:46:47+00:00"
|
||||
"time": "2026-07-28T08:25:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.43.0",
|
||||
"version": "v1.42.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "533d68cf99c8f8ee2e8893c59ed59192e92cfd74"
|
||||
"reference": "51b5ff5ba85452b31ec6f55490b08148612339d9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/533d68cf99c8f8ee2e8893c59ed59192e92cfd74",
|
||||
"reference": "533d68cf99c8f8ee2e8893c59ed59192e92cfd74",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/51b5ff5ba85452b31ec6f55490b08148612339d9",
|
||||
"reference": "51b5ff5ba85452b31ec6f55490b08148612339d9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10694,7 +10612,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.43.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.42.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10714,20 +10632,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-23T14:40:04+00:00"
|
||||
"time": "2026-08-24T10:51:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.43.0",
|
||||
"version": "v1.42.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b"
|
||||
"reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/ebd57ccc7edb93d632e184efbe7693d2517bab3b",
|
||||
"reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/aa20edea75bd9c48cfecc8360922e5a6e5c44502",
|
||||
"reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10779,7 +10697,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.43.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.42.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10799,20 +10717,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-23T22:02:09+00:00"
|
||||
"time": "2026-08-07T06:33:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.43.0",
|
||||
"version": "v1.38.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72"
|
||||
"reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/4d5d331bf731e0aedbc6b2f5e61135b7b7996a72",
|
||||
"reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
|
||||
"reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10864,7 +10782,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10884,20 +10802,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-24T15:19:04+00:00"
|
||||
"time": "2026-05-27T06:59:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.43.0",
|
||||
"version": "v1.37.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74"
|
||||
"reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74",
|
||||
"reference": "9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411",
|
||||
"reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10948,7 +10866,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.43.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.37.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10968,7 +10886,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-25T15:50:05+00:00"
|
||||
"time": "2026-04-10T16:19:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php81",
|
||||
@@ -11052,16 +10970,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php83",
|
||||
"version": "v1.43.0",
|
||||
"version": "v1.41.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php83.git",
|
||||
"reference": "80ccff923a8d61f73ebe9da0aa94e25232f004ce"
|
||||
"reference": "5ea99087fb99c273a9b9236ed4c31e78b16103c6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/80ccff923a8d61f73ebe9da0aa94e25232f004ce",
|
||||
"reference": "80ccff923a8d61f73ebe9da0aa94e25232f004ce",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/5ea99087fb99c273a9b9236ed4c31e78b16103c6",
|
||||
"reference": "5ea99087fb99c273a9b9236ed4c31e78b16103c6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11108,7 +11026,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php83/tree/v1.43.0"
|
||||
"source": "https://github.com/symfony/polyfill-php83/tree/v1.41.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11128,20 +11046,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-25T15:50:05+00:00"
|
||||
"time": "2026-07-01T12:47:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php84",
|
||||
"version": "v1.43.0",
|
||||
"version": "v1.38.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php84.git",
|
||||
"reference": "22c6548499cbe5c5bb072fc0c42312dff062a015"
|
||||
"reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/22c6548499cbe5c5bb072fc0c42312dff062a015",
|
||||
"reference": "22c6548499cbe5c5bb072fc0c42312dff062a015",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa",
|
||||
"reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11188,7 +11106,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php84/tree/v1.43.0"
|
||||
"source": "https://github.com/symfony/polyfill-php84/tree/v1.38.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11208,20 +11126,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-23T22:01:09+00:00"
|
||||
"time": "2026-05-26T12:51:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php85",
|
||||
"version": "v1.43.0",
|
||||
"version": "v1.41.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php85.git",
|
||||
"reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6"
|
||||
"reference": "255fab485aaa1006ed411040c42aecd7b5302d7a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/86a42cbcc07adc331481a5ab310a4024bfc227f6",
|
||||
"reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/255fab485aaa1006ed411040c42aecd7b5302d7a",
|
||||
"reference": "255fab485aaa1006ed411040c42aecd7b5302d7a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11268,7 +11186,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php85/tree/v1.43.0"
|
||||
"source": "https://github.com/symfony/polyfill-php85/tree/v1.41.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11288,20 +11206,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-25T15:46:47+00:00"
|
||||
"time": "2026-07-01T12:47:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-uuid",
|
||||
"version": "v1.43.0",
|
||||
"version": "v1.37.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-uuid.git",
|
||||
"reference": "b23ff8245cc5c4479ea2be3d0132d2e6dd433993"
|
||||
"reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/b23ff8245cc5c4479ea2be3d0132d2e6dd433993",
|
||||
"reference": "b23ff8245cc5c4479ea2be3d0132d2e6dd433993",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/26dfec253c4cf3e51b541b52ddf7e42cb0908e94",
|
||||
"reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11351,7 +11269,7 @@
|
||||
"uuid"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.43.0"
|
||||
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.37.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11371,7 +11289,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-24T05:20:52+00:00"
|
||||
"time": "2026-04-10T16:19:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
@@ -11440,16 +11358,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/routing",
|
||||
"version": "v7.4.20",
|
||||
"version": "v7.4.18",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/routing.git",
|
||||
"reference": "2bacb72be5eadeaf9874d5accb75bfb33d21c74b"
|
||||
"reference": "ddd558991e98f693ae6bf5063cc1b0362c6bbec3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/2bacb72be5eadeaf9874d5accb75bfb33d21c74b",
|
||||
"reference": "2bacb72be5eadeaf9874d5accb75bfb33d21c74b",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/ddd558991e98f693ae6bf5063cc1b0362c6bbec3",
|
||||
"reference": "ddd558991e98f693ae6bf5063cc1b0362c6bbec3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11501,7 +11419,7 @@
|
||||
"url"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/routing/tree/v7.4.20"
|
||||
"source": "https://github.com/symfony/routing/tree/v7.4.18"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11521,7 +11439,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-28T19:09:50+00:00"
|
||||
"time": "2026-08-17T13:12:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
@@ -11877,16 +11795,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/uid",
|
||||
"version": "v7.4.20",
|
||||
"version": "v7.4.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/uid.git",
|
||||
"reference": "a96bbdb02a04ff3b5592cee6741b03edc78b56aa"
|
||||
"reference": "69d732355a139c6f8881337d28515aa01f12b8be"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/uid/zipball/a96bbdb02a04ff3b5592cee6741b03edc78b56aa",
|
||||
"reference": "a96bbdb02a04ff3b5592cee6741b03edc78b56aa",
|
||||
"url": "https://api.github.com/repos/symfony/uid/zipball/69d732355a139c6f8881337d28515aa01f12b8be",
|
||||
"reference": "69d732355a139c6f8881337d28515aa01f12b8be",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11931,7 +11849,7 @@
|
||||
"uuid"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/uid/tree/v7.4.20"
|
||||
"source": "https://github.com/symfony/uid/tree/v7.4.17"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11951,7 +11869,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-23T16:18:28+00:00"
|
||||
"time": "2026-08-11T07:38:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
@@ -12042,16 +11960,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v7.4.20",
|
||||
"version": "v7.4.18",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "0222bf4dfaa1e3ceb8fff579635d655f2950d5a7"
|
||||
"reference": "4cef939e55b8a21c5780418de0d98ab00d0736e1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/0222bf4dfaa1e3ceb8fff579635d655f2950d5a7",
|
||||
"reference": "0222bf4dfaa1e3ceb8fff579635d655f2950d5a7",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/4cef939e55b8a21c5780418de0d98ab00d0736e1",
|
||||
"reference": "4cef939e55b8a21c5780418de0d98ab00d0736e1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -12094,7 +12012,7 @@
|
||||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v7.4.20"
|
||||
"source": "https://github.com/symfony/yaml/tree/v7.4.18"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -12114,7 +12032,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-09-26T06:31:10+00:00"
|
||||
"time": "2026-08-30T00:47:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tbachert/spi",
|
||||
@@ -12170,16 +12088,16 @@
|
||||
},
|
||||
{
|
||||
"name": "technikermathe/blade-lucide-icons",
|
||||
"version": "v3.183.0",
|
||||
"version": "v3.182.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PascaleBeier/blade-lucide-icons.git",
|
||||
"reference": "c0f8034b71f18c97edfe9911e16a0b2f4ef017c6"
|
||||
"reference": "11253aa7d9aa7430da61d3534c62dc69a95b703b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PascaleBeier/blade-lucide-icons/zipball/c0f8034b71f18c97edfe9911e16a0b2f4ef017c6",
|
||||
"reference": "c0f8034b71f18c97edfe9911e16a0b2f4ef017c6",
|
||||
"url": "https://api.github.com/repos/PascaleBeier/blade-lucide-icons/zipball/11253aa7d9aa7430da61d3534c62dc69a95b703b",
|
||||
"reference": "11253aa7d9aa7430da61d3534c62dc69a95b703b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -12229,9 +12147,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PascaleBeier/blade-lucide-icons/issues",
|
||||
"source": "https://github.com/PascaleBeier/blade-lucide-icons/tree/v3.183.0"
|
||||
"source": "https://github.com/PascaleBeier/blade-lucide-icons/tree/v3.182.0"
|
||||
},
|
||||
"time": "2026-09-30T02:58:19+00:00"
|
||||
"time": "2026-09-25T02:29:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tijsverkoyen/css-to-inline-styles",
|
||||
|
||||
@@ -133,13 +133,6 @@ services:
|
||||
|
||||
stoic:
|
||||
image: ghcr.io/lexx27/stoic:latest
|
||||
# Runs as root — the app container's entrypoint.sh chowns the whole
|
||||
# storage/ tree to www-data on every boot (docker/entrypoint.sh),
|
||||
# and Stoic's own image user isn't www-data or in its group, so it
|
||||
# can't write thumbnails into storage/app/public/stoic/ otherwise
|
||||
# (libvips reports this as "Failed to write VipsImage to file").
|
||||
# Same fix already applied in docker-compose.dev.yml.
|
||||
user: root
|
||||
ports:
|
||||
- "127.0.0.1:${STOIC_PORT:-2727}:2727"
|
||||
environment:
|
||||
|
||||
+3
-27
@@ -1,5 +1,3 @@
|
||||
fastcgi_cache_path /tmp/fcgi_cache levels=1:2 keys_zone=app_cache:10m max_size=256m inactive=10m use_temp_path=off;
|
||||
|
||||
upstream php_fpm {
|
||||
server app:9000;
|
||||
keepalive 16;
|
||||
@@ -19,23 +17,9 @@ server {
|
||||
open_file_cache_min_uses 2;
|
||||
open_file_cache_errors on;
|
||||
|
||||
# --- FastCGI cache bypass rules ---
|
||||
set $skip_cache 0;
|
||||
|
||||
if ($request_method = POST) { set $skip_cache 1; }
|
||||
if ($request_uri ~* "^/(boboko|up)") { set $skip_cache 1; }
|
||||
if ($query_string) { set $skip_cache 1; }
|
||||
# Any logged-in request must never be served a cached response —
|
||||
# the cache key is URL-only ($scheme$request_method$host$request_uri,
|
||||
# see fastcgi_cache_key below), with no per-session variation. Without
|
||||
# this, the first cached hit on an authenticated GET page (e.g.
|
||||
# /account) gets replayed verbatim to every other visitor of that same
|
||||
# URL for up to fastcgi_cache_valid's 10m window — a real account/
|
||||
# session data leak, not just a staleness bug. Laravel's session
|
||||
# cookie name is env('SESSION_COOKIE', Str::slug(APP_NAME).'-session')
|
||||
# (config/session.php) — APP_NAME varies per environment, so this
|
||||
# matches the fixed '-session' suffix rather than a hardcoded name.
|
||||
if ($http_cookie ~* "-session") { set $skip_cache 1; }
|
||||
# No FastCGI page cache: every Laravel response is per-visitor (session
|
||||
# cookie, CSRF token, cart, login state), so a shared cache keyed on the
|
||||
# URL replays one visitor's page and session cookie to everyone else.
|
||||
|
||||
# Vite build assets — content-hashed filenames, safe to cache forever
|
||||
location /build/ {
|
||||
@@ -84,14 +68,6 @@ server {
|
||||
fastcgi_buffers 16 16k;
|
||||
fastcgi_buffer_size 32k;
|
||||
fastcgi_keep_conn on;
|
||||
|
||||
fastcgi_cache app_cache;
|
||||
fastcgi_cache_key "$scheme$request_method$host$request_uri";
|
||||
fastcgi_cache_valid 200 10m;
|
||||
fastcgi_cache_bypass $skip_cache;
|
||||
fastcgi_no_cache $skip_cache;
|
||||
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
}
|
||||
|
||||
location /stoic/ {
|
||||
|
||||
Generated
+2
-2
@@ -20,8 +20,8 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@boboko/core": {
|
||||
"version": "0.31.0",
|
||||
"resolved": "git+https://code.radical-elements.com/boboko/core.git#207cb133634feddb28efc9675726307ab99df205",
|
||||
"version": "0.27.2",
|
||||
"resolved": "git+https://code.radical-elements.com/boboko/core.git#332bf92e4429cf5b787e106b9e8613d912dfcc4a",
|
||||
"dependencies": {
|
||||
"@hotwired/stimulus": "^3.2.2",
|
||||
"leaflet": "^1.9.4"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 90 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 62 KiB |
@@ -1,12 +1,12 @@
|
||||
@import "tailwindcss";
|
||||
@import "./fonts.css";
|
||||
@import "./dropdown.css";
|
||||
@import "./checkout.css";
|
||||
|
||||
/* checkout.css themes the cart/checkout module (.bbk-* classes). Its base
|
||||
styles (boboko-core's checkout.css) are plain, unlayered CSS, so theme
|
||||
overrides must be plain rules too, never inside @layer components/utilities,
|
||||
which would lose to them. */
|
||||
/* Note for anyone theming the checkout module (resources/css/checkout.css,
|
||||
.bbk-* classes): it's deliberately plain, unlayered CSS, not inside any
|
||||
@layer — so override it with plain rules here too, not from inside
|
||||
@layer components/utilities, which would lose to it. See checkout.css's
|
||||
file-level comment for why. */
|
||||
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
|
||||
@source '../../storage/framework/views/*.php';
|
||||
@source '../**/*.blade.php';
|
||||
|
||||
@@ -1,504 +0,0 @@
|
||||
/*
|
||||
* 3dealer theme for the cart + checkout module (.bbk-* classes).
|
||||
*
|
||||
* Sits on top of boboko-core's generic checkout.css, which loads first (its
|
||||
* own @vite entry). Rules here are deliberately plain and unlayered: the base
|
||||
* file is unlayered too, and an unlayered rule beats any rule inside
|
||||
* @layer components/utilities. Don't wrap this file in a layer.
|
||||
*
|
||||
* Everything maps onto an existing 3dealer pattern (x-ui.input, x-ui.button,
|
||||
* x-ui.checkbox, x-ui.quantity, account-page headings). Square everywhere:
|
||||
* no border-radius.
|
||||
*/
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
TOKENS — the module's own variables, pointed at ours
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
:root {
|
||||
--bbk-font: var(--font-sans);
|
||||
|
||||
--bbk-color-text: var(--color-black);
|
||||
--bbk-color-muted: var(--color-neutral-500);
|
||||
--bbk-color-bg: var(--color-neutral-200);
|
||||
--bbk-color-bg-muted: var(--color-neutral-300);
|
||||
--bbk-color-border: var(--color-black);
|
||||
--bbk-color-accent: var(--color-black);
|
||||
--bbk-color-accent-text: var(--color-neutral-200);
|
||||
--bbk-color-danger: var(--color-red-600);
|
||||
|
||||
--bbk-radius: 0;
|
||||
--bbk-radius-sm: 0;
|
||||
--bbk-shadow: none;
|
||||
}
|
||||
|
||||
.bbk-cart,
|
||||
.bbk-checkout-page,
|
||||
.bbk-confirmation {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
SHARED CONTROLS
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
|
||||
/* Primary CTA — x-ui.button "primary". The offset black block is a
|
||||
box-shadow here rather than .btn-primary's ::before/::after, because the
|
||||
module's buttons have no inner <span> to lift the label above a
|
||||
positioned ::before. Same look, same easing. No `uppercase`: the module
|
||||
markup can't carry the class strip-accents.js needs for Greek. */
|
||||
.bbk-cart-checkout,
|
||||
.bbk-checkout-continue {
|
||||
@apply border-black bg-neutral-200 px-6 py-3.5 text-base font-bold italic text-black;
|
||||
box-shadow: 10px 10px 0 var(--color-black);
|
||||
transition: box-shadow 0.35s cubic-bezier(0.2, 0.78, 0.12, 0.86);
|
||||
}
|
||||
|
||||
.bbk-checkout-continue {
|
||||
@apply px-[46px] py-5 text-[19px];
|
||||
}
|
||||
|
||||
.bbk-cart-checkout:hover,
|
||||
.bbk-checkout-continue:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.bbk-cart-checkout:not(:disabled):hover,
|
||||
.bbk-checkout-continue:not(:disabled):hover {
|
||||
box-shadow: 0 0 0 var(--color-black);
|
||||
}
|
||||
|
||||
.bbk-cart-checkout:disabled,
|
||||
.bbk-checkout-continue:disabled {
|
||||
@apply opacity-50;
|
||||
}
|
||||
|
||||
/* Secondary button — x-ui.button "secondary", size sm */
|
||||
.bbk-cart-coupon-submit {
|
||||
@apply border-black bg-transparent px-6 py-2 text-sm font-semibold transition-colors hover:bg-black hover:text-neutral-200;
|
||||
}
|
||||
|
||||
/* Text inputs — x-ui.input: bottom border only, transparent */
|
||||
.bbk-field-input,
|
||||
.bbk-cart-coupon-input,
|
||||
.bbk-checkout-box-now-locker-search {
|
||||
@apply border-0 border-b border-black bg-transparent px-0 py-2 placeholder:text-neutral-400;
|
||||
}
|
||||
|
||||
.bbk-field-input:focus,
|
||||
.bbk-field-input:focus-visible,
|
||||
.bbk-cart-coupon-input:focus-visible,
|
||||
.bbk-checkout-box-now-locker-search:focus {
|
||||
@apply outline-none;
|
||||
}
|
||||
|
||||
.bbk-field-input:disabled {
|
||||
@apply cursor-not-allowed bg-transparent text-black opacity-50;
|
||||
}
|
||||
|
||||
.bbk-field-input--error {
|
||||
@apply border-red-600;
|
||||
}
|
||||
|
||||
/* x-ui.select — native arrow off, arrow-down icon in its place */
|
||||
select.bbk-field-input {
|
||||
@apply cursor-pointer appearance-none pr-10;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' stroke='black'%3E%3Cpath fill='none' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M12 5V19M12 19L6 13M12 19L18 13'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 1rem center;
|
||||
background-size: 16px;
|
||||
}
|
||||
|
||||
/* x-ui.textarea */
|
||||
textarea.bbk-field-input {
|
||||
@apply resize-none;
|
||||
}
|
||||
|
||||
/* Read-only value (the store's single country) — x-ui.input read-only */
|
||||
.bbk-field-static {
|
||||
@apply border-0 border-b border-black bg-transparent px-0 py-2 text-black opacity-60;
|
||||
}
|
||||
|
||||
/* x-ui.field */
|
||||
.bbk-field {
|
||||
@apply gap-2;
|
||||
}
|
||||
|
||||
.bbk-field-row {
|
||||
@apply gap-8;
|
||||
}
|
||||
|
||||
.bbk-field-label {
|
||||
@apply text-black;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
.bbk-field-error {
|
||||
@apply text-sm;
|
||||
}
|
||||
|
||||
/* x-ui.checkbox — square box, brand fill when ticked. Radios in the
|
||||
shipping/payment cards use the same box (square design, no circles). */
|
||||
.bbk-checkbox {
|
||||
@apply gap-3;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.bbk-checkbox--stacked {
|
||||
@apply mt-0 text-sm;
|
||||
}
|
||||
|
||||
.bbk-checkbox--stacked a,
|
||||
.bbk-checkout-withdrawal a,
|
||||
.bbk-checkout-login-prompt a,
|
||||
.bbk-checkout-note a {
|
||||
@apply underline hover:no-underline;
|
||||
}
|
||||
|
||||
.bbk-checkbox input[type="checkbox"],
|
||||
.bbk-checkout-shipping-option input[type="radio"],
|
||||
.bbk-checkout-payment-option input[type="radio"] {
|
||||
@apply relative size-4 shrink-0 cursor-pointer appearance-none border border-current bg-transparent;
|
||||
}
|
||||
|
||||
.bbk-checkbox input[type="checkbox"]:checked::after,
|
||||
.bbk-checkout-shipping-option input[type="radio"]:checked::after,
|
||||
.bbk-checkout-payment-option input[type="radio"]:checked::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 2px;
|
||||
background: var(--color-brand);
|
||||
}
|
||||
|
||||
.bbk-checkbox input[type="checkbox"]:focus-visible,
|
||||
.bbk-checkout-shipping-option input[type="radio"]:focus-visible,
|
||||
.bbk-checkout-payment-option input[type="radio"]:focus-visible {
|
||||
@apply outline-2 outline-offset-2 outline-current;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
CART DRAWER
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.bbk-cart-panel {
|
||||
@apply border-l border-black;
|
||||
}
|
||||
|
||||
.bbk-cart-panel-header {
|
||||
@apply px-8 py-6;
|
||||
}
|
||||
|
||||
.bbk-cart-heading {
|
||||
@apply font-display text-h4 font-extrabold;
|
||||
}
|
||||
|
||||
/* Icon buttons — same as the header's icons */
|
||||
.bbk-cart-dismiss,
|
||||
.bbk-cart-item-remove {
|
||||
@apply text-black transition-opacity hover:bg-transparent hover:text-black hover:opacity-70;
|
||||
}
|
||||
|
||||
.bbk-cart-panel-body {
|
||||
@apply p-8;
|
||||
}
|
||||
|
||||
.bbk-cart-error {
|
||||
@apply px-8;
|
||||
}
|
||||
|
||||
.bbk-cart-items {
|
||||
@apply mb-8 gap-6;
|
||||
}
|
||||
|
||||
.bbk-cart-item-media img,
|
||||
.bbk-confirmation-line .bbk-cart-item-media img {
|
||||
@apply border border-black;
|
||||
}
|
||||
|
||||
.bbk-cart-item-title {
|
||||
@apply font-bold;
|
||||
}
|
||||
|
||||
.bbk-cart-item-variant,
|
||||
.bbk-cart-item-unit,
|
||||
.bbk-line-fields {
|
||||
@apply text-sm;
|
||||
}
|
||||
|
||||
.bbk-cart-item-total {
|
||||
@apply font-display font-bold;
|
||||
}
|
||||
|
||||
/* Quantity stepper — x-ui.quantity */
|
||||
.bbk-cart-qty-btn {
|
||||
@apply size-8 bg-transparent text-xl font-bold text-black transition-colors hover:bg-black hover:text-neutral-200;
|
||||
}
|
||||
|
||||
.bbk-cart-qty-input {
|
||||
@apply h-8 w-10 bg-transparent font-display font-bold;
|
||||
}
|
||||
|
||||
.bbk-cart-qty-btn:focus-visible,
|
||||
.bbk-cart-qty-input:focus-visible {
|
||||
@apply outline-2 outline-offset-0 outline-black;
|
||||
}
|
||||
|
||||
/* Summary */
|
||||
.bbk-cart-summary {
|
||||
@apply gap-3 pt-6;
|
||||
}
|
||||
|
||||
.bbk-cart-coupon {
|
||||
@apply mb-3;
|
||||
}
|
||||
|
||||
.bbk-cart-coupon-form {
|
||||
@apply items-end gap-4;
|
||||
}
|
||||
|
||||
/* Applied coupon — x-ui.status box */
|
||||
.bbk-cart-coupon-applied {
|
||||
@apply border-black bg-brand px-6 py-3 text-black;
|
||||
}
|
||||
|
||||
.bbk-cart-coupon-remove {
|
||||
@apply text-sm text-black underline hover:text-black hover:no-underline;
|
||||
}
|
||||
|
||||
.bbk-cart-summary-row--total {
|
||||
@apply mt-3 pt-4 font-display text-xl font-extrabold;
|
||||
}
|
||||
|
||||
.bbk-cart-summary .bbk-cart-checkout {
|
||||
@apply mt-6;
|
||||
}
|
||||
|
||||
.bbk-cart-empty {
|
||||
@apply py-10;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
CHECKOUT PAGE
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.bbk-checkout-page {
|
||||
@apply max-w-6xl px-8 py-16 lg:px-16;
|
||||
}
|
||||
|
||||
.bbk-checkout-heading {
|
||||
@apply mb-12 font-display text-h3 font-black tracking-tight sm:text-h2;
|
||||
}
|
||||
|
||||
.bbk-checkout {
|
||||
@apply gap-16;
|
||||
}
|
||||
|
||||
.bbk-checkout-main {
|
||||
@apply gap-10;
|
||||
}
|
||||
|
||||
.bbk-checkout-section {
|
||||
@apply gap-8 pb-10;
|
||||
}
|
||||
|
||||
.bbk-checkout-section-heading,
|
||||
.bbk-checkout-summary-heading {
|
||||
@apply font-display text-h4 font-extrabold;
|
||||
}
|
||||
|
||||
.bbk-checkout-note,
|
||||
.bbk-checkout-status,
|
||||
.bbk-checkout-withdrawal,
|
||||
.bbk-checkout-error {
|
||||
@apply text-sm;
|
||||
}
|
||||
|
||||
.bbk-checkout-login-prompt a {
|
||||
@apply font-bold;
|
||||
}
|
||||
|
||||
.bbk-invoice,
|
||||
.bbk-checkout-shipping-fields {
|
||||
@apply gap-8;
|
||||
}
|
||||
|
||||
/* Shipping / payment choices — bordered cards that fill black when picked,
|
||||
like x-ui.option-buttons' pressed state. */
|
||||
.bbk-checkout-shipping-option,
|
||||
.bbk-checkout-payment-option,
|
||||
.bbk-checkout-shipping-confirmed {
|
||||
@apply gap-4 px-6 py-4;
|
||||
}
|
||||
|
||||
.bbk-checkout-shipping-option,
|
||||
.bbk-checkout-payment-option {
|
||||
@apply transition-colors;
|
||||
}
|
||||
|
||||
.bbk-checkout-shipping-option:has(input:checked),
|
||||
.bbk-checkout-payment-option:has(input:checked) {
|
||||
@apply bg-black text-neutral-200;
|
||||
}
|
||||
|
||||
.bbk-checkout-shipping-option-name,
|
||||
.bbk-checkout-payment-option-name {
|
||||
@apply font-bold;
|
||||
}
|
||||
|
||||
.bbk-checkout-shipping-option-description {
|
||||
@apply text-sm;
|
||||
}
|
||||
|
||||
.bbk-checkout-shipping-option:has(input:checked) .bbk-checkout-shipping-option-description {
|
||||
@apply text-neutral-400;
|
||||
}
|
||||
|
||||
.bbk-checkout-shipping-option-price {
|
||||
@apply font-display font-bold;
|
||||
}
|
||||
|
||||
/* Box Now locker picker. Leaflet's own CSS arrives in a lazy chunk (after
|
||||
this file), so its selectors are scoped under the picker to outrank it. */
|
||||
.bbk-checkout-box-now-locker {
|
||||
@apply mt-4 gap-4 p-6;
|
||||
}
|
||||
|
||||
.bbk-checkout-box-now-locker-label {
|
||||
@apply text-base font-bold;
|
||||
}
|
||||
|
||||
.bbk-checkout-box-now-locker-map {
|
||||
@apply border border-black;
|
||||
}
|
||||
|
||||
.bbk-checkout-box-now-locker-chosen {
|
||||
@apply text-sm font-bold;
|
||||
}
|
||||
|
||||
.bbk-checkout-box-now-locker .leaflet-popup-content-wrapper,
|
||||
.bbk-box-now-popup-image,
|
||||
.bbk-box-now-popup-name::before {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.bbk-checkout-box-now-locker .leaflet-popup-content-wrapper {
|
||||
@apply border border-black bg-neutral-200 shadow-none;
|
||||
}
|
||||
|
||||
.bbk-checkout-box-now-locker .leaflet-popup-tip {
|
||||
@apply bg-neutral-200;
|
||||
}
|
||||
|
||||
.bbk-box-now-popup-name::before {
|
||||
@apply bg-brand;
|
||||
}
|
||||
|
||||
.bbk-box-now-popup-note {
|
||||
@apply bg-neutral-300;
|
||||
}
|
||||
|
||||
.bbk-box-now-popup-select {
|
||||
@apply border border-black bg-black text-sm text-neutral-200 transition-colors hover:bg-neutral-200 hover:text-black;
|
||||
}
|
||||
|
||||
.bbk-box-now-popup-select:hover {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.bbk-box-now-popup-select--selected,
|
||||
.bbk-box-now-popup-select--selected:hover {
|
||||
@apply border-neutral-500 bg-neutral-500 text-neutral-200;
|
||||
}
|
||||
|
||||
/* Order summary column. The header is sticky too (lg:h-26), so the
|
||||
aside sticks below it rather than behind it. */
|
||||
.bbk-checkout-aside {
|
||||
@apply top-32;
|
||||
}
|
||||
|
||||
.bbk-checkout-summary {
|
||||
@apply bg-transparent p-8;
|
||||
}
|
||||
|
||||
.bbk-checkout-summary-heading {
|
||||
@apply mb-6;
|
||||
}
|
||||
|
||||
/* Payment */
|
||||
.bbk-payment-element {
|
||||
@apply my-2;
|
||||
}
|
||||
|
||||
/* Processing overlay — square spinner, no radius */
|
||||
.bbk-spinner {
|
||||
@apply size-8;
|
||||
border-color: var(--color-neutral-300);
|
||||
border-top-color: var(--color-black);
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
CONFIRMATION PAGE — same shape as account/orders/show
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
.bbk-confirmation {
|
||||
@apply max-w-4xl px-8 py-16 lg:px-16;
|
||||
}
|
||||
|
||||
.bbk-confirmation-heading {
|
||||
@apply mb-12 font-display text-h3 font-black tracking-tight sm:text-h2;
|
||||
}
|
||||
|
||||
.bbk-confirmation-meta {
|
||||
@apply mb-6 gap-3 border-y border-black py-6;
|
||||
}
|
||||
|
||||
.bbk-confirmation-meta-row {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.bbk-confirmation-meta-row dt {
|
||||
@apply text-sm;
|
||||
}
|
||||
|
||||
.bbk-confirmation-meta-row dd {
|
||||
@apply font-bold;
|
||||
}
|
||||
|
||||
.bbk-confirmation .bbk-checkout-note + .bbk-checkout-note {
|
||||
@apply mt-2;
|
||||
}
|
||||
|
||||
.bbk-confirmation-body {
|
||||
@apply my-12 gap-12;
|
||||
}
|
||||
|
||||
.bbk-confirmation-lines {
|
||||
@apply gap-6;
|
||||
}
|
||||
|
||||
.bbk-confirmation-line-name {
|
||||
@apply font-bold;
|
||||
}
|
||||
|
||||
.bbk-confirmation-line-qty {
|
||||
@apply font-normal;
|
||||
}
|
||||
|
||||
.bbk-confirmation-line-total {
|
||||
@apply font-display font-bold;
|
||||
}
|
||||
|
||||
.bbk-confirmation-lines .bbk-cart-summary {
|
||||
@apply mt-6;
|
||||
}
|
||||
|
||||
.bbk-confirmation-addresses {
|
||||
@apply gap-8;
|
||||
}
|
||||
|
||||
.bbk-confirmation-address-heading {
|
||||
@apply mb-3 font-display text-xl font-extrabold;
|
||||
}
|
||||
|
||||
.bbk-address-lines {
|
||||
@apply text-base text-black;
|
||||
}
|
||||
@@ -3,25 +3,20 @@ import { Controller } from "@hotwired/stimulus";
|
||||
const SCROLL_STEP = 1;
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["main", "thumb", "track", "arrow", "lightbox", "lightboxImage", "lightboxCounter"];
|
||||
static targets = ["main", "thumb", "track", "lightbox", "lightboxImage", "lightboxCounter"];
|
||||
|
||||
connect() {
|
||||
this.offset = 0;
|
||||
this.lightboxIndex = 0;
|
||||
this.#syncHeight();
|
||||
|
||||
// Main image and thumbnails resize as their images load and on viewport
|
||||
// changes; re-sync the track height and arrow visibility each time.
|
||||
this._resizeObserver = new ResizeObserver(() => this.#syncHeight());
|
||||
this._resizeObserver.observe(this.mainTarget);
|
||||
this.thumbTargets.forEach((t) => this._resizeObserver.observe(t));
|
||||
this.mainTarget.addEventListener("load", () => this.#syncHeight());
|
||||
|
||||
this._onKeydown = this.#handleKeydown.bind(this);
|
||||
document.addEventListener("keydown", this._onKeydown);
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this._resizeObserver?.disconnect();
|
||||
document.removeEventListener("keydown", this._onKeydown);
|
||||
}
|
||||
|
||||
@@ -108,14 +103,6 @@ export default class extends Controller {
|
||||
if (h > 0) {
|
||||
this.trackTarget.style.maxHeight = h + "px";
|
||||
}
|
||||
this.#toggleArrows();
|
||||
}
|
||||
|
||||
// Arrows stay in the layout (invisible, not hidden) so the thumbnail
|
||||
// column keeps its alignment with the main image.
|
||||
#toggleArrows() {
|
||||
const overflowing = this.trackTarget.scrollHeight > this.trackTarget.clientHeight;
|
||||
this.arrowTargets.forEach((a) => a.classList.toggle("invisible", !overflowing));
|
||||
}
|
||||
|
||||
#handleKeydown(e) {
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<li class="grid grid-cols-2 gap-x-6 gap-y-2 border-b border-black py-5 sm:grid-cols-[1fr_1fr_1.5fr_1fr_auto] sm:items-center">
|
||||
<span>
|
||||
<span class="sr-only">{{ __('storefront.orders.date') }}:</span>
|
||||
{{ $order->placed_at->inDisplayTimezone()->format('d/m/Y') }}
|
||||
{{ $order->placed_at->format('d/m/Y') }}
|
||||
</span>
|
||||
<span class="text-right font-bold sm:text-left">
|
||||
<span class="sr-only">{{ __('storefront.orders.number') }}:</span>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<dl class="grid grid-cols-1 gap-6 border-y border-black py-6 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<div class="flex flex-col gap-1">
|
||||
<dt class="text-sm text-neutral-500">{{ __('storefront.orders.date') }}</dt>
|
||||
<dd>{{ $order->placed_at->inDisplayTimezone()->format('d/m/Y') }}</dd>
|
||||
<dd>{{ $order->placed_at->format('d/m/Y') }}</dd>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-1">
|
||||
@@ -51,70 +51,15 @@
|
||||
<dd>{{ $shippingLine->description }}</dd>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@foreach ($shipments as $shipment)
|
||||
<div class="flex flex-col gap-1">
|
||||
<dt class="text-sm text-neutral-500">{{ __('storefront.orders.tracking') }}</dt>
|
||||
<dd class="break-all">{{ $shipment->tracking_reference }}</dd>
|
||||
</div>
|
||||
@endforeach
|
||||
</dl>
|
||||
|
||||
{{-- Shipment tracking: the history we sync from the courier. Only
|
||||
couriers without an integration link out to their own site. --}}
|
||||
@if ($shipments->isNotEmpty())
|
||||
<section class="flex flex-col gap-6" aria-labelledby="order-tracking-heading">
|
||||
<h2 id="order-tracking-heading" class="font-display text-h4 font-extrabold">{{ __('storefront.orders.tracking') }}</h2>
|
||||
|
||||
@foreach ($shipments as $shipment)
|
||||
@php
|
||||
$history = $shipment->shipmentInfo->sortByDesc('occurred_at');
|
||||
$latest = $history->first();
|
||||
@endphp
|
||||
|
||||
<div class="flex flex-col gap-5 border-b border-black pb-6">
|
||||
<dl class="grid grid-cols-1 gap-6 sm:grid-cols-3">
|
||||
<div class="flex flex-col gap-1">
|
||||
<dt class="text-sm text-neutral-500">{{ __('storefront.orders.shipment') }}</dt>
|
||||
<dd>{{ $shipment->carrierLabel() }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<dt class="text-sm text-neutral-500">{{ __('storefront.orders.voucher_number') }}</dt>
|
||||
<dd class="break-all">{{ $shipment->tracking_reference }}</dd>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<dt class="text-sm text-neutral-500">{{ __('storefront.orders.shipment_status') }}</dt>
|
||||
<dd class="font-bold">{{ __('storefront.tracking_status.'.($latest?->status->value ?? 'pending')) }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
@if ($trackingUrl = $shipment->trackingUrl())
|
||||
<a href="{{ $trackingUrl }}" target="_blank" rel="noopener" class="inline-flex items-center gap-2 self-start text-sm underline hover:no-underline">
|
||||
{{ __('storefront.orders.track_on_carrier') }}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
<div class="flex flex-col gap-3">
|
||||
<h3 class="text-sm text-neutral-500">{{ __('storefront.orders.tracking_history') }}</h3>
|
||||
|
||||
@if ($history->isEmpty())
|
||||
<p class="text-sm">{{ __('storefront.orders.tracking_empty') }}</p>
|
||||
@else
|
||||
<ol class="flex flex-col gap-3">
|
||||
@foreach ($history as $checkpoint)
|
||||
<li class="flex flex-col gap-0.5 sm:flex-row sm:gap-6">
|
||||
<time datetime="{{ $checkpoint->occurred_at->toIso8601String() }}" class="shrink-0 text-sm text-neutral-500 sm:w-36">
|
||||
{{ $checkpoint->occurred_at->inDisplayTimezone()->format('d/m/Y H:i') }}
|
||||
</time>
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<span>{{ __('storefront.tracking_status.'.$checkpoint->status->value) }}</span>
|
||||
@if ($details = collect([$checkpoint->location, ($checkpoint->status->value === 'unknown' || $checkpoint->carrier_status === 'manual') ? $checkpoint->message : null])->filter()->implode(' · '))
|
||||
<span class="text-sm text-neutral-500">{{ $details }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
</ol>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</section>
|
||||
@endif
|
||||
|
||||
{{-- Items + totals --}}
|
||||
<section class="flex flex-col gap-6" aria-labelledby="order-items-heading">
|
||||
<h2 id="order-items-heading" class="font-display text-h4 font-extrabold">{{ __('storefront.orders.items') }}</h2>
|
||||
|
||||
@@ -37,8 +37,7 @@ class="relative flex gap-4 items-start"
|
||||
<button
|
||||
type="button"
|
||||
data-action="click->product-gallery#scrollUp"
|
||||
data-product-gallery-target="arrow"
|
||||
class="gallery-arrow invisible w-full flex items-center justify-center py-2"
|
||||
class="gallery-arrow w-full flex items-center justify-center py-2"
|
||||
aria-label="Scroll thumbnails up"
|
||||
><x-ui.icon name="arrow-up" :size="30" /></button>
|
||||
|
||||
@@ -68,8 +67,7 @@ class="block w-full shrink-0 border border-black overflow-hidden "
|
||||
<button
|
||||
type="button"
|
||||
data-action="click->product-gallery#scrollDown"
|
||||
data-product-gallery-target="arrow"
|
||||
class="gallery-arrow invisible w-full flex items-center justify-center py-2"
|
||||
class="gallery-arrow w-full flex items-center justify-center py-2"
|
||||
aria-label="Scroll thumbnails down"
|
||||
><x-ui.icon name="arrow-down" :size="30" /></button>
|
||||
</div>
|
||||
@@ -233,9 +231,14 @@ class="flex flex-col gap-6"
|
||||
['id' => 'reviews', 'label' => __('storefront.product.reviews') . ' (' . $product['reviews']['count'] . ')'],
|
||||
]">
|
||||
<x-slot name="description">
|
||||
<div class="leading-7 [&_p]:mt-4 [&_ul]:flex [&_ul]:flex-col [&_ul]:gap-3 [&_ul]:text-neutral-600 [&_ul]:list-disc [&_ul]:list-outside [&_ul]:pl-5">
|
||||
<div class="leading-7 [&_p]:mt-4">
|
||||
{!! $product['description'] !!}
|
||||
</div>
|
||||
<ul class="mt-8 flex flex-col gap-3 text-neutral-600 list-disc list-outside pl-5">
|
||||
<li>Όλα τα προϊόντα εκτυπώνονται και προετοιμάζονται κατά παραγγελία. Ο χρόνος προετοιμασίας κυμαίνεται μεταξύ 2 και 7 εργάσιμων ημερών.</li>
|
||||
<li>Όλα τα προϊόντα κατασκευάζονται με τρισδιάστατη εκτύπωση σε ειδικούς εκτυπωτές πλαστικού υλικού. Πιθανώς να έχουν εμφανείς γραμμές ένωσης, στρώσεις εκτύπωσης υλικού και μικρές ατέλειες. Είναι φυσιολογικό για το αποτέλεσμα αυτής της δημιουργικής διαδικασίας.</li>
|
||||
<li>Όλα τα προϊόντα είναι σχεδιασμένα και κατασκευασμένα είτε για διακόσμηση είτε για χρήση σε λογικά, ρεαλιστικά πλαίσια. Υπερβολική ισχύς, υψηλότατες θερμοκρασίες και αποσυναρμολόγηση μπορεί να προκαλέσουν ζημιά στο προϊόν για την οποία δεν ευθύνεται το 3Dealer.</li>
|
||||
</ul>
|
||||
</x-slot>
|
||||
<x-slot name="reviews">
|
||||
@if(session('reviewSubmitted'))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{{-- Core passes the order, its reference and its active shipments. Greek on purpose: sent from the queue in the app default locale. --}}
|
||||
{{-- Core passes only the order reference here (and the amount for payment emails). Greek on purpose: sent from the queue in the app default locale. --}}
|
||||
@extends('emails.layout')
|
||||
|
||||
@section('title', "Η παραγγελία σου στάλθηκε")
|
||||
@@ -10,23 +10,12 @@
|
||||
Η παραγγελία σου στάλθηκε
|
||||
</h1>
|
||||
|
||||
<p style="margin:0 0 24px;">Η παραγγελία σου <strong>#{{ $reference }}</strong> είναι καθ’ οδόν. Θα τη λάβεις σύντομα.</p>
|
||||
<p style="margin:0 0 32px;">Η παραγγελία σου <strong>#{{ $reference }}</strong> είναι καθ’ οδόν. Θα τη λάβεις σύντομα.</p>
|
||||
|
||||
@foreach ($shipments ?? [] as $shipment)
|
||||
<p style="margin:0 0 8px;">
|
||||
{{ $shipment->carrierLabel() }} · Αριθμός αποστολής: <strong>{{ $shipment->tracking_reference }}</strong>
|
||||
@if ($carrierUrl = $shipment->trackingUrl())
|
||||
· <a href="{{ $carrierUrl }}" style="color:#000000;text-decoration:underline;">Παρακολούθηση στη σελίδα του courier</a>
|
||||
@endif
|
||||
</p>
|
||||
@endforeach
|
||||
|
||||
<div style="height:24px;"></div>
|
||||
|
||||
{{-- Orders with an account: their order page shows the tracking history we sync from the courier. --}}
|
||||
@include('emails.partials.button', $order->customer_id
|
||||
? ['url' => route('account.orders.show', ['locale' => 'el', 'orderId' => $order->id]), 'label' => 'Παρακολούθηση παραγγελίας']
|
||||
: ['url' => route('account.orders', ['locale' => 'el']), 'label' => 'Οι παραγγελίες μου'])
|
||||
@include('emails.partials.button', [
|
||||
'url' => route('account.orders', ['locale' => 'el']),
|
||||
'label' => 'Οι παραγγελίες μου',
|
||||
])
|
||||
@endsection
|
||||
|
||||
@section('footer')
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
<p style="margin:0 0 24px;">
|
||||
Λάβαμε την παραγγελία σου <strong>#{{ $reference }}</strong>
|
||||
στις {{ $order->placed_at?->inDisplayTimezone()->format('d/m/Y') }}.
|
||||
στις {{ $order->placed_at?->format('d/m/Y') }}.
|
||||
Θα σε ενημερώσουμε με email μόλις σταλεί.
|
||||
</p>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user