Add public Amazon referral page
This commit is contained in:
parent
59db92713a
commit
119f486bb8
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\PublicAccess;
|
||||
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class AmazonReferralController
|
||||
{
|
||||
public function index(Request $request): View
|
||||
{
|
||||
return view('public.amazon-referral', [
|
||||
'associateTag' => $this->associateTag(),
|
||||
'defaultQuery' => trim((string) $request->query('q', '')),
|
||||
'defaultAsin' => trim((string) $request->query('asin', '')),
|
||||
'defaultUrl' => trim((string) $request->query('url', '')),
|
||||
]);
|
||||
}
|
||||
|
||||
public function go(Request $request): RedirectResponse
|
||||
{
|
||||
$asin = $this->normalizeAsin((string) $request->query('asin', ''));
|
||||
if ($asin !== null) {
|
||||
return redirect()->away($this->appendAssociateTag('https://www.amazon.it/dp/' . rawurlencode($asin)));
|
||||
}
|
||||
|
||||
$url = trim((string) $request->query('url', ''));
|
||||
if ($url !== '' && filter_var($url, FILTER_VALIDATE_URL)) {
|
||||
return redirect()->away($this->appendAssociateTag($this->normalizeAmazonUrl($url)));
|
||||
}
|
||||
|
||||
$query = trim((string) $request->query('q', ''));
|
||||
if ($query !== '') {
|
||||
return redirect()->away($this->appendAssociateTag('https://www.amazon.it/s?k=' . rawurlencode($query)));
|
||||
}
|
||||
|
||||
return redirect()->route('public.amazon.index');
|
||||
}
|
||||
|
||||
private function associateTag(): string
|
||||
{
|
||||
$tag = trim((string) config('services.amazon.referral_tag', ''));
|
||||
|
||||
if ($tag === '') {
|
||||
$tag = trim((string) config('catalog.amazon.associate_tag', 'netgescon-21'));
|
||||
}
|
||||
|
||||
return $tag !== '' ? $tag : 'netgescon-21';
|
||||
}
|
||||
|
||||
private function appendAssociateTag(string $url): string
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
if (! is_array($parts)) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$query = [];
|
||||
parse_str((string) ($parts['query'] ?? ''), $query);
|
||||
$query['tag'] = $this->associateTag();
|
||||
|
||||
$base = ($parts['scheme'] ?? 'https') . '://' . ($parts['host'] ?? 'www.amazon.it') . ($parts['path'] ?? '');
|
||||
|
||||
return $base . '?' . http_build_query($query);
|
||||
}
|
||||
|
||||
private function normalizeAmazonUrl(string $url): string
|
||||
{
|
||||
$asin = $this->extractAsinFromUrl($url);
|
||||
|
||||
if ($asin !== null) {
|
||||
return 'https://www.amazon.it/dp/' . rawurlencode($asin);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
private function extractAsinFromUrl(string $url): ?string
|
||||
{
|
||||
if (preg_match('~/(?:dp|gp/product)/([A-Z0-9]{10})(?:[/?]|$)~i', $url, $matches)) {
|
||||
return strtoupper($matches[1]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function normalizeAsin(string $value): ?string
|
||||
{
|
||||
$value = strtoupper(trim($value));
|
||||
$value = preg_replace('/[^A-Z0-9]/', '', $value) ?? '';
|
||||
|
||||
return preg_match('/^[A-Z0-9]{10}$/', $value) ? $value : null;
|
||||
}
|
||||
}
|
||||
242
resources/views/public/amazon-referral.blade.php
Normal file
242
resources/views/public/amazon-referral.blade.php
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Amazon con Tag NetGescon</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #f3efe7;
|
||||
--card: rgba(255, 255, 255, 0.92);
|
||||
--ink: #1f2937;
|
||||
--muted: #6b7280;
|
||||
--line: rgba(31, 41, 55, 0.12);
|
||||
--accent: #c66a1f;
|
||||
--accent-dark: #8a4313;
|
||||
--shadow: 0 20px 50px rgba(82, 52, 24, 0.14);
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Georgia, "Times New Roman", serif;
|
||||
color: var(--ink);
|
||||
background:
|
||||
radial-gradient(circle at top left, rgba(198, 106, 31, 0.16), transparent 28%),
|
||||
radial-gradient(circle at bottom right, rgba(39, 99, 87, 0.14), transparent 24%),
|
||||
var(--bg);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.shell {
|
||||
width: min(1100px, calc(100% - 32px));
|
||||
margin: 32px auto;
|
||||
}
|
||||
|
||||
.hero {
|
||||
display: grid;
|
||||
gap: 20px;
|
||||
grid-template-columns: 1.2fr 0.8fr;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.panel {
|
||||
background: var(--card);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 24px;
|
||||
box-shadow: var(--shadow);
|
||||
padding: 28px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0 0 12px;
|
||||
font-size: clamp(2rem, 3vw, 3.2rem);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 1rem;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 14px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(198, 106, 31, 0.24);
|
||||
background: rgba(198, 106, 31, 0.1);
|
||||
color: var(--accent-dark);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 18px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.form-card h2,
|
||||
.tips h2 {
|
||||
margin: 0 0 14px;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.field {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
font-size: 0.85rem;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 14px 16px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid var(--line);
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
font-size: 1rem;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline: 2px solid rgba(198, 106, 31, 0.22);
|
||||
border-color: rgba(198, 106, 31, 0.45);
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.button,
|
||||
.button-secondary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 48px;
|
||||
padding: 0 18px;
|
||||
border-radius: 14px;
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
transition: transform 120ms ease, box-shadow 120ms ease;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.button {
|
||||
background: linear-gradient(135deg, var(--accent), #df8d2b);
|
||||
color: white;
|
||||
box-shadow: 0 12px 24px rgba(198, 106, 31, 0.24);
|
||||
}
|
||||
|
||||
.button-secondary {
|
||||
background: white;
|
||||
color: var(--ink);
|
||||
border: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.button:hover,
|
||||
.button-secondary:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.tips ul {
|
||||
margin: 0;
|
||||
padding-left: 18px;
|
||||
color: var(--muted);
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.mini-link {
|
||||
color: var(--accent-dark);
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.hero,
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="shell">
|
||||
<section class="hero">
|
||||
<div class="panel">
|
||||
<div class="tag">Tag attivo: {{ $associateTag }}</div>
|
||||
<h1>Apri Amazon con il link affiliato NetGescon</h1>
|
||||
<p>Questa pagina pubblica serve ad aprire Amazon con il tag corretto. Puoi cercare un prodotto, incollare un ASIN oppure ripulire un link Amazon già esistente aggiungendo automaticamente il tag.</p>
|
||||
<p style="margin-top:12px;font-size:0.95rem;color:#8a4313;"><strong>In qualità di Affiliato Amazon io ricevo un guadagno dagli acquisti idonei.</strong></p>
|
||||
</div>
|
||||
|
||||
<div class="panel tips">
|
||||
<h2>Come usarla</h2>
|
||||
<ul>
|
||||
<li>Se conosci il nome del prodotto usa la ricerca per testo.</li>
|
||||
<li>Se hai già il codice ASIN, incollalo e apri direttamente la scheda prodotto.</li>
|
||||
<li>Se ti mandano un link Amazon, incollalo qui e il sistema aggiunge il tag automaticamente.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid">
|
||||
<form class="panel form-card" method="GET" action="{{ route('public.amazon.go') }}">
|
||||
<h2>Ricerca per testo</h2>
|
||||
<div class="field">
|
||||
<label for="q">Prodotto da cercare</label>
|
||||
<input id="q" name="q" type="text" value="{{ $defaultQuery }}" placeholder="Es. notebook lenovo thinkpad" />
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="button" type="submit">Apri ricerca Amazon</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="panel form-card" method="GET" action="{{ route('public.amazon.go') }}">
|
||||
<h2>Apertura diretta ASIN</h2>
|
||||
<div class="field">
|
||||
<label for="asin">ASIN Amazon</label>
|
||||
<input id="asin" name="asin" type="text" value="{{ $defaultAsin }}" placeholder="Es. B0DN6PD8QS" />
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="button" type="submit">Apri scheda prodotto</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="panel form-card" method="GET" action="{{ route('public.amazon.go') }}">
|
||||
<h2>Normalizza link Amazon</h2>
|
||||
<div class="field">
|
||||
<label for="url">Link prodotto</label>
|
||||
<input id="url" name="url" type="text" value="{{ $defaultUrl }}" placeholder="https://www.amazon.it/dp/..." />
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="button" type="submit">Apri link con tag</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="panel" style="margin-top: 20px;">
|
||||
<h2 style="margin:0 0 10px;">Esempio pronto</h2>
|
||||
<p style="margin-bottom:14px;">Puoi già distribuire anche un link diretto, ad esempio per il prodotto che stavamo testando.</p>
|
||||
<a class="mini-link" href="{{ route('public.amazon.go', ['asin' => 'B0DN6PD8QS']) }}">Apri B0DN6PD8QS con tag NetGescon</a>
|
||||
<div style="margin-top:14px;font-size:0.9rem;color:#6b7280;">Link base da far girare: {{ route('public.amazon.index') }}</div>
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -45,6 +45,11 @@
|
|||
return redirect('/admin-filament');
|
||||
});
|
||||
|
||||
Route::prefix('public/amazon')->name('public.amazon.')->group(function () {
|
||||
Route::get('/', [\App\Http\Controllers\PublicAccess\AmazonReferralController::class, 'index'])->name('index');
|
||||
Route::get('/go', [\App\Http\Controllers\PublicAccess\AmazonReferralController::class, 'go'])->name('go');
|
||||
});
|
||||
|
||||
Route::middleware('signed')->prefix('public/letture-acqua')->name('public.water-reading.')->group(function () {
|
||||
Route::get('/', [\App\Http\Controllers\PublicAccess\WaterReadingRequestController::class, 'show'])->name('show');
|
||||
Route::post('/', [\App\Http\Controllers\PublicAccess\WaterReadingRequestController::class, 'store'])->name('store');
|
||||
|
|
@ -168,6 +173,15 @@
|
|||
->name('diagnostica_fatture_elettroniche');
|
||||
});
|
||||
|
||||
Route::middleware(['role:super-admin|admin|amministratore|collaboratore|fornitore'])->prefix('admin')->name('admin.')->group(function () {
|
||||
// Fatture elettroniche ricevute (azioni)
|
||||
Route::get('fatture-elettroniche/{fattura}/download-xml', [\App\Http\Controllers\Admin\FattureElettronicheRicevuteController::class, 'downloadXml'])
|
||||
->name('fatture-elettroniche.download-xml');
|
||||
|
||||
Route::get('fatture-elettroniche/{fattura}/download-pdf', [\App\Http\Controllers\Admin\FattureElettronicheRicevuteController::class, 'downloadPdf'])
|
||||
->name('fatture-elettroniche.download-pdf');
|
||||
});
|
||||
|
||||
// --- ADMIN / AMMINISTRATORE PANEL ---
|
||||
Route::middleware(['role:super-admin|admin|amministratore|collaboratore'])->prefix('admin')->name('admin.')->group(function () {
|
||||
// Dashboard dell'amministratore
|
||||
|
|
@ -185,13 +199,6 @@
|
|||
Route::get('filament/stabili/{stabile}', [FilamentBridgeController::class, 'openStabile'])
|
||||
->name('filament.stabili.open');
|
||||
|
||||
// Fatture elettroniche ricevute (azioni)
|
||||
Route::get('fatture-elettroniche/{fattura}/download-xml', [\App\Http\Controllers\Admin\FattureElettronicheRicevuteController::class, 'downloadXml'])
|
||||
->name('fatture-elettroniche.download-xml');
|
||||
|
||||
Route::get('fatture-elettroniche/{fattura}/download-pdf', [\App\Http\Controllers\Admin\FattureElettronicheRicevuteController::class, 'downloadPdf'])
|
||||
->name('fatture-elettroniche.download-pdf');
|
||||
|
||||
// Dashboard per categorie del menu
|
||||
Route::prefix('dashboards')->name('dashboards.')->group(function () {
|
||||
Route::get('/stabili', [\App\Http\Controllers\Admin\CategoryDashboardController::class, 'stabili'])->name('stabili');
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user