954ba8f059
Schema: - online_orders (token-tracked, status workflow, delivery method/fee) - online_order_items (price snapshot, fulfilled flag) - part_cross_refs (OEM/equivalent codes for search) - parts.is_published (shop visibility) Storefront (ShopController, tenant subdomain, /shop): - Catalog with search across name/article/brand/cross-refs, category + in-stock filters, live stock, white-label themed layout - Part detail page with cross-ref codes - VIN search → VinDecoder → guided catalog search - Session cart (per-tenant key), guest checkout, order confirmation page - Respects settings.shop.enabled (404 when off); tenant-guarded Part::searchPublished matches cross-ref articles via whereHas. Order notifications (ShopOrderNotifier, best-effort): - Staff: Web Push to active users - Customer: Telegram if phone matches a linked client Filament (tenant): - OnlineOrderResource under "Magazin" nav group, status workflow, items relation, "Onorează" action issues stock via WarehouseService (FIFO) - PartResource: is_published toggle + column + bulk publish/unpublish + CrossRefsRelationManager - Settings: shop section (enable, delivery methods, fee, free-over) - Landing page: shop button when enabled Tests (6 new): - catalog 404 when disabled; lists published only; cross-ref search; order placement (token + items + total); fulfill issues stock; cross-tenant token isolation Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
121 lines
4.5 KiB
PHP
121 lines
4.5 KiB
PHP
<!DOCTYPE html>
|
||
<html lang="ro">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>{{ $name }} — autoservice {{ $city ?? '' }}</title>
|
||
@if ($faviconUrl)
|
||
<link rel="icon" href="{{ $faviconUrl }}">
|
||
@endif
|
||
<style>
|
||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||
body { font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; color: #1f2937; line-height: 1.5; }
|
||
|
||
.hero {
|
||
background: linear-gradient(135deg, {{ $themeColor }}, {{ $themeColor }}cc);
|
||
color: #fff; padding: 80px 20px; text-align: center;
|
||
}
|
||
.hero img { max-height: 80px; margin-bottom: 16px; }
|
||
.hero h1 { font-size: 38px; font-weight: 700; margin-bottom: 12px; }
|
||
.hero p { font-size: 18px; opacity: .92; max-width: 600px; margin: 0 auto; }
|
||
|
||
.section { padding: 60px 20px; max-width: 1100px; margin: 0 auto; }
|
||
.section h2 { font-size: 28px; font-weight: 700; margin-bottom: 24px; text-align: center; }
|
||
|
||
.services-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; }
|
||
.service-card {
|
||
background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 12px;
|
||
padding: 24px; text-align: center; transition: transform .15s;
|
||
}
|
||
.service-card:hover { transform: translateY(-2px); border-color: {{ $themeColor }}; }
|
||
.service-card .icon { font-size: 32px; margin-bottom: 12px; }
|
||
.service-card h3 { font-size: 16px; font-weight: 600; }
|
||
|
||
.info { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px; }
|
||
.info-block { padding: 24px; background: #f9fafb; border-radius: 12px; }
|
||
.info-block h3 { font-size: 16px; font-weight: 600; margin-bottom: 12px; color: {{ $themeColor }}; }
|
||
.info-block p { font-size: 14px; color: #4b5563; margin-bottom: 6px; }
|
||
|
||
.cta { background: {{ $themeColor }}; color: #fff; text-align: center; padding: 60px 20px; }
|
||
.cta h2 { font-size: 26px; margin-bottom: 16px; }
|
||
.cta a {
|
||
display: inline-block; padding: 14px 32px;
|
||
background: #fff; color: {{ $themeColor }};
|
||
border-radius: 8px; text-decoration: none; font-weight: 600;
|
||
margin: 8px; transition: opacity .15s;
|
||
}
|
||
.cta a:hover { opacity: .9; }
|
||
|
||
footer { background: #1f2937; color: #9ca3af; padding: 24px; text-align: center; font-size: 13px; }
|
||
footer a { color: #d1d5db; text-decoration: none; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<header class="hero">
|
||
@if ($logoUrl)
|
||
<img src="{{ $logoUrl }}" alt="logo">
|
||
@endif
|
||
<h1>{{ $name }}</h1>
|
||
<p>Autoservice profesional{{ $city ? ' — ' . $city : '' }}. Diagnostic, reparații, piese, ITP.</p>
|
||
@if (! empty($shopEnabled))
|
||
<a href="/shop" style="display:inline-block;margin-top:20px;background:#fff;color:{{ $themeColor }};padding:12px 28px;border-radius:8px;font-weight:700;text-decoration:none;">
|
||
🛒 Magazin piese online
|
||
</a>
|
||
@endif
|
||
</header>
|
||
|
||
@if (! empty($services))
|
||
<section class="section">
|
||
<h2>Servicii oferite</h2>
|
||
<div class="services-grid">
|
||
@foreach ($services as $s)
|
||
<div class="service-card">
|
||
<div class="icon">🔧</div>
|
||
<h3>{{ $s }}</h3>
|
||
</div>
|
||
@endforeach
|
||
</div>
|
||
</section>
|
||
@endif
|
||
|
||
<section class="section">
|
||
<div class="info">
|
||
<div class="info-block">
|
||
<h3>📍 Locație & contact</h3>
|
||
@if ($city) <p><b>Oraș:</b> {{ $city }}</p> @endif
|
||
@if ($phone) <p><b>Telefon:</b> <a href="tel:{{ $phone }}" style="color:inherit;">{{ $phone }}</a></p> @endif
|
||
@if ($email) <p><b>Email:</b> <a href="mailto:{{ $email }}" style="color:inherit;">{{ $email }}</a></p> @endif
|
||
</div>
|
||
<div class="info-block">
|
||
<h3>🕒 Program de lucru</h3>
|
||
<p>Luni – Vineri: 08:00 – 18:00</p>
|
||
<p>Sâmbătă: 09:00 – 14:00</p>
|
||
<p>Duminică: închis</p>
|
||
</div>
|
||
@if (! empty($cars))
|
||
<div class="info-block">
|
||
<h3>🚗 Mărci suportate</h3>
|
||
<p>{{ implode(', ', array_slice($cars, 0, 12)) }}@if (count($cars) > 12), …@endif</p>
|
||
</div>
|
||
@endif
|
||
</div>
|
||
</section>
|
||
|
||
<section class="cta">
|
||
<h2>Rezervă o programare</h2>
|
||
@if ($phone)
|
||
<a href="tel:{{ $phone }}">📞 {{ $phone }}</a>
|
||
@endif
|
||
@if ($email)
|
||
<a href="mailto:{{ $email }}">✉ {{ $email }}</a>
|
||
@endif
|
||
</section>
|
||
|
||
<footer>
|
||
© {{ date('Y') }} {{ $name }} · powered by AutoCRM
|
||
</footer>
|
||
|
||
</body>
|
||
</html>
|