Konto: Rechnung direkt auf der Seite ansehen statt nur Download-Platzhalter
Der bisherige "Rechnung (PDF)"-Knopf war ein toter Link (href="#"). Jetzt öffnet "Rechnung ansehen" pro Bestellung ein natives Dialog-Fenster direkt auf der Seite mit vollständiger Rechnung: Rechnungsnummer/-datum, Verkäufer, Rechnungsempfänger (live mit dem aktuellen Kontonamen befüllt), Artikeltabelle mit Einzel-/Gesamtpreisen und dem §19-UStG-Hinweis — kein Herunterladen nötig, schließbar per Kreuz, Schließen-Knopf oder Klick auf den abgedunkelten Hintergrund. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
fac404190f
commit
e2a19db663
+20
-4
@@ -229,7 +229,11 @@ export const ui = {
|
|||||||
noArrivedOrders: "Noch keine angekommenen Bestellungen — hier erscheinen deine Bestellungen, sobald sie geliefert wurden.",
|
noArrivedOrders: "Noch keine angekommenen Bestellungen — hier erscheinen deine Bestellungen, sobald sie geliefert wurden.",
|
||||||
ordersTitle: "📦 Meine Bestellungen",
|
ordersTitle: "📦 Meine Bestellungen",
|
||||||
orderNo: "Bestellung", orderDate: "Bestellt am", orderTotal: "Gesamt", orderItems: "Artikel",
|
orderNo: "Bestellung", orderDate: "Bestellt am", orderTotal: "Gesamt", orderItems: "Artikel",
|
||||||
trackingLabel: "Sendungsverfolgung", trackingBtn: "Sendung verfolgen →", invoiceBtn: "Rechnung (PDF)", reorderBtn: "Nochmal bestellen",
|
trackingLabel: "Sendungsverfolgung", trackingBtn: "Sendung verfolgen →", invoiceBtn: "Rechnung ansehen", reorderBtn: "Nochmal bestellen",
|
||||||
|
invoiceTitle: "Rechnung", invoiceNumberLabel: "Rechnungsnummer", invoiceDateLabel: "Rechnungsdatum",
|
||||||
|
invoiceSellerLabel: "Verkäufer", invoiceBillToLabel: "Rechnungsempfänger",
|
||||||
|
invoiceItemLabel: "Artikel", invoiceQtyLabel: "Menge", invoiceUnitPriceLabel: "Einzelpreis", invoiceSumLabel: "Gesamtbetrag",
|
||||||
|
invoiceCloseBtn: "Schließen",
|
||||||
statusBezahlt: "Bezahlt", statusBearbeitung: "In Bearbeitung", statusVersandVorbereitet: "Versand vorbereitet", statusVersendet: "Versendet", statusAbgeschlossen: "Abgeschlossen",
|
statusBezahlt: "Bezahlt", statusBearbeitung: "In Bearbeitung", statusVersandVorbereitet: "Versand vorbereitet", statusVersendet: "Versendet", statusAbgeschlossen: "Abgeschlossen",
|
||||||
wishlistTitle: "🩵 Meine Wunschliste", wishlistEmpty: "Deine Wunschliste ist noch leer — stöbere im Shop und speichere deine Lieblingsstücke mit dem Herz-Symbol.",
|
wishlistTitle: "🩵 Meine Wunschliste", wishlistEmpty: "Deine Wunschliste ist noch leer — stöbere im Shop und speichere deine Lieblingsstücke mit dem Herz-Symbol.",
|
||||||
recentTitle: "🕘 Zuletzt angesehen",
|
recentTitle: "🕘 Zuletzt angesehen",
|
||||||
@@ -463,7 +467,11 @@ export const ui = {
|
|||||||
noArrivedOrders: "No delivered orders yet — your orders will appear here once they've arrived.",
|
noArrivedOrders: "No delivered orders yet — your orders will appear here once they've arrived.",
|
||||||
ordersTitle: "📦 My orders",
|
ordersTitle: "📦 My orders",
|
||||||
orderNo: "Order", orderDate: "Ordered on", orderTotal: "Total", orderItems: "Items",
|
orderNo: "Order", orderDate: "Ordered on", orderTotal: "Total", orderItems: "Items",
|
||||||
trackingLabel: "Tracking", trackingBtn: "Track shipment →", invoiceBtn: "Invoice (PDF)", reorderBtn: "Order again",
|
trackingLabel: "Tracking", trackingBtn: "Track shipment →", invoiceBtn: "View invoice", reorderBtn: "Order again",
|
||||||
|
invoiceTitle: "Invoice", invoiceNumberLabel: "Invoice number", invoiceDateLabel: "Invoice date",
|
||||||
|
invoiceSellerLabel: "Seller", invoiceBillToLabel: "Billed to",
|
||||||
|
invoiceItemLabel: "Item", invoiceQtyLabel: "Qty", invoiceUnitPriceLabel: "Unit price", invoiceSumLabel: "Total amount",
|
||||||
|
invoiceCloseBtn: "Close",
|
||||||
statusBezahlt: "Paid", statusBearbeitung: "In progress", statusVersandVorbereitet: "Preparing shipment", statusVersendet: "Shipped", statusAbgeschlossen: "Completed",
|
statusBezahlt: "Paid", statusBearbeitung: "In progress", statusVersandVorbereitet: "Preparing shipment", statusVersendet: "Shipped", statusAbgeschlossen: "Completed",
|
||||||
wishlistTitle: "🩵 My wishlist", wishlistEmpty: "Your wishlist is still empty — browse the shop and save your favourites with the heart icon.",
|
wishlistTitle: "🩵 My wishlist", wishlistEmpty: "Your wishlist is still empty — browse the shop and save your favourites with the heart icon.",
|
||||||
recentTitle: "🕘 Recently viewed",
|
recentTitle: "🕘 Recently viewed",
|
||||||
@@ -697,7 +705,11 @@ export const ui = {
|
|||||||
noArrivedOrders: "No kei aacho Bstellige — da erschine dini Bstellige, sobald sie glifert worde sind.",
|
noArrivedOrders: "No kei aacho Bstellige — da erschine dini Bstellige, sobald sie glifert worde sind.",
|
||||||
ordersTitle: "📦 Mini Bstellige",
|
ordersTitle: "📦 Mini Bstellige",
|
||||||
orderNo: "Bstellig", orderDate: "Bstellt am", orderTotal: "Total", orderItems: "Artikel",
|
orderNo: "Bstellig", orderDate: "Bstellt am", orderTotal: "Total", orderItems: "Artikel",
|
||||||
trackingLabel: "Sändigsverfolgig", trackingBtn: "Sändig verfolge →", invoiceBtn: "Rächnig (PDF)", reorderBtn: "Nomal bstelle",
|
trackingLabel: "Sändigsverfolgig", trackingBtn: "Sändig verfolge →", invoiceBtn: "Rächnig aluege", reorderBtn: "Nomal bstelle",
|
||||||
|
invoiceTitle: "Rächnig", invoiceNumberLabel: "Rächnigsnummere", invoiceDateLabel: "Rächnigsdatum",
|
||||||
|
invoiceSellerLabel: "Verchöifer", invoiceBillToLabel: "Rächnigsempfänger",
|
||||||
|
invoiceItemLabel: "Artikel", invoiceQtyLabel: "Mengi", invoiceUnitPriceLabel: "Ystückspreis", invoiceSumLabel: "Gsamtbetrag",
|
||||||
|
invoiceCloseBtn: "Schlüsse",
|
||||||
statusBezahlt: "Zahlt", statusBearbeitung: "I dr Bearbeitig", statusVersandVorbereitet: "Versand vorbereitet", statusVersendet: "Verschickt", statusAbgeschlossen: "Abgschlosse",
|
statusBezahlt: "Zahlt", statusBearbeitung: "I dr Bearbeitig", statusVersandVorbereitet: "Versand vorbereitet", statusVersendet: "Verschickt", statusAbgeschlossen: "Abgschlosse",
|
||||||
wishlistTitle: "🩵 Mini Wunschlischte", wishlistEmpty: "Dini Wunschlischte isch no leer — lueg im Shop verbi und spicher dini Lieblingssächeli mit em Härz-Symbol.",
|
wishlistTitle: "🩵 Mini Wunschlischte", wishlistEmpty: "Dini Wunschlischte isch no leer — lueg im Shop verbi und spicher dini Lieblingssächeli mit em Härz-Symbol.",
|
||||||
recentTitle: "🕘 Zletscht aagluegt",
|
recentTitle: "🕘 Zletscht aagluegt",
|
||||||
@@ -931,7 +943,11 @@ export const ui = {
|
|||||||
noArrivedOrders: "Aucune commande livrée pour le moment — vos commandes apparaîtront ici dès qu'elles seront arrivées.",
|
noArrivedOrders: "Aucune commande livrée pour le moment — vos commandes apparaîtront ici dès qu'elles seront arrivées.",
|
||||||
ordersTitle: "📦 Mes commandes",
|
ordersTitle: "📦 Mes commandes",
|
||||||
orderNo: "Commande", orderDate: "Commandé le", orderTotal: "Total", orderItems: "Articles",
|
orderNo: "Commande", orderDate: "Commandé le", orderTotal: "Total", orderItems: "Articles",
|
||||||
trackingLabel: "Suivi", trackingBtn: "Suivre l'envoi →", invoiceBtn: "Facture (PDF)", reorderBtn: "Commander à nouveau",
|
trackingLabel: "Suivi", trackingBtn: "Suivre l'envoi →", invoiceBtn: "Voir la facture", reorderBtn: "Commander à nouveau",
|
||||||
|
invoiceTitle: "Facture", invoiceNumberLabel: "Numéro de facture", invoiceDateLabel: "Date de facture",
|
||||||
|
invoiceSellerLabel: "Vendeur", invoiceBillToLabel: "Facturé à",
|
||||||
|
invoiceItemLabel: "Article", invoiceQtyLabel: "Qté", invoiceUnitPriceLabel: "Prix unitaire", invoiceSumLabel: "Montant total",
|
||||||
|
invoiceCloseBtn: "Fermer",
|
||||||
statusBezahlt: "Payée", statusBearbeitung: "En préparation", statusVersandVorbereitet: "Envoi en préparation", statusVersendet: "Expédiée", statusAbgeschlossen: "Terminée",
|
statusBezahlt: "Payée", statusBearbeitung: "En préparation", statusVersandVorbereitet: "Envoi en préparation", statusVersendet: "Expédiée", statusAbgeschlossen: "Terminée",
|
||||||
wishlistTitle: "🩵 Ma liste de souhaits", wishlistEmpty: "Votre liste de souhaits est encore vide — parcourez la boutique et enregistrez vos coups de cœur avec l'icône en forme de cœur.",
|
wishlistTitle: "🩵 Ma liste de souhaits", wishlistEmpty: "Votre liste de souhaits est encore vide — parcourez la boutique et enregistrez vos coups de cœur avec l'icône en forme de cœur.",
|
||||||
recentTitle: "🕘 Vus récemment",
|
recentTitle: "🕘 Vus récemment",
|
||||||
|
|||||||
@@ -141,13 +141,72 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
<span class="order-total">{t.accountDash.orderTotal}: <strong>{formatPrice(b.summe, lang)}</strong></span>
|
<span class="order-total">{t.accountDash.orderTotal}: <strong>{formatPrice(b.summe, lang)}</strong></span>
|
||||||
<div class="order-actions">
|
<div class="order-actions">
|
||||||
{b.tracking && <a class="btn btn-outline btn-sm" href={`https://www.dhl.de/de/privatkunden/dhl-sendungsverfolgung.html?piececode=${b.tracking}`} target="_blank" rel="noopener">{t.accountDash.trackingBtn}</a>}
|
{b.tracking && <a class="btn btn-outline btn-sm" href={`https://www.dhl.de/de/privatkunden/dhl-sendungsverfolgung.html?piececode=${b.tracking}`} target="_blank" rel="noopener">{t.accountDash.trackingBtn}</a>}
|
||||||
<a class="btn btn-outline btn-sm" href="#">{t.accountDash.invoiceBtn}</a>
|
<button type="button" class="btn btn-outline btn-sm" data-open-invoice={`invoice-${b.nummer}`}>{t.accountDash.invoiceBtn}</button>
|
||||||
<a class="btn btn-outline btn-sm" href="/ch/shop/">{t.accountDash.reorderBtn}</a>
|
<a class="btn btn-outline btn-sm" href="/ch/shop/">{t.accountDash.reorderBtn}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{b.tracking && (
|
{b.tracking && (
|
||||||
<p class="small order-tracking-no">{t.accountDash.trackingLabel}: <code>{b.tracking}</code></p>
|
<p class="small order-tracking-no">{t.accountDash.trackingLabel}: <code>{b.tracking}</code></p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Rechnung direkt auf der Seite ansehen (natives <dialog>, siehe Skript unten) —
|
||||||
|
kein Download nötig. Empfängername wird beim Öffnen live aus dem Konto befüllt
|
||||||
|
(siehe .invoice-billto-name), Adresse ist bewusst dieselbe Platzhalter-Adresse
|
||||||
|
wie oben unter "Meine Daten". */}
|
||||||
|
<dialog class="invoice-dialog" id={`invoice-${b.nummer}`}>
|
||||||
|
<div class="invoice-card">
|
||||||
|
<div class="invoice-head">
|
||||||
|
<div>
|
||||||
|
<h3>{t.accountDash.invoiceTitle}</h3>
|
||||||
|
<p class="invoice-meta">{t.accountDash.invoiceNumberLabel}: {b.nummer}</p>
|
||||||
|
<p class="invoice-meta">{t.accountDash.invoiceDateLabel}: {b.datum}</p>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="invoice-close" data-close-invoice aria-label={t.accountDash.invoiceCloseBtn}>✕</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="invoice-parties">
|
||||||
|
<div>
|
||||||
|
<h4>{t.accountDash.invoiceSellerLabel}</h4>
|
||||||
|
<p>Van's DIY & Bastelbedarf</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4>{t.accountDash.invoiceBillToLabel}</h4>
|
||||||
|
<p><span class="invoice-billto-name">–</span><br />Musterstraße 1<br />10115 Berlin<br />Deutschland</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="invoice-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{t.accountDash.invoiceItemLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceQtyLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceUnitPriceLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceSumLabel}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{b.artikel.map((a) => (
|
||||||
|
<tr>
|
||||||
|
<td>{a.name}</td>
|
||||||
|
<td>{a.menge}</td>
|
||||||
|
<td>{formatPrice(a.preis, lang)}</td>
|
||||||
|
<td>{formatPrice(a.preis * a.menge, lang)}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
<tr class="invoice-total-row">
|
||||||
|
<td colspan="3">{t.accountDash.orderTotal}</td>
|
||||||
|
<td>{formatPrice(b.summe, lang)}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="invoice-vat-note">{t.common.vatNote}</p>
|
||||||
|
|
||||||
|
<div class="invoice-foot">
|
||||||
|
<button type="button" class="btn btn-outline btn-sm" data-close-invoice>{t.accountDash.invoiceCloseBtn}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -316,6 +375,10 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
el.style.backgroundImage = bg;
|
el.style.backgroundImage = bg;
|
||||||
el.textContent = text;
|
el.textContent = text;
|
||||||
});
|
});
|
||||||
|
// Empfängername in allen (schon gerenderten) Rechnungs-Dialogen live mit aktualisieren.
|
||||||
|
document.querySelectorAll<HTMLElement>(".invoice-billto-name").forEach((el) => {
|
||||||
|
el.textContent = anzeigeName(a) || fallbackName;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
renderProfil();
|
renderProfil();
|
||||||
window.addEventListener("account:changed", renderProfil);
|
window.addEventListener("account:changed", renderProfil);
|
||||||
@@ -351,6 +414,25 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
window.location.href = loginPath;
|
window.location.href = loginPath;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Rechnung direkt auf der Seite ansehen: natives <dialog> pro Bestellung, geöffnet/geschlossen
|
||||||
|
// per Button — kein Download nötig, kein Verlassen der Seite.
|
||||||
|
document.querySelectorAll<HTMLButtonElement>("[data-open-invoice]").forEach((btn) => {
|
||||||
|
btn.addEventListener("click", () => {
|
||||||
|
const id = btn.dataset.openInvoice;
|
||||||
|
const dialog = id ? (document.getElementById(id) as HTMLDialogElement | null) : null;
|
||||||
|
dialog?.showModal();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document.querySelectorAll<HTMLDialogElement>(".invoice-dialog").forEach((dialog) => {
|
||||||
|
dialog.querySelectorAll<HTMLButtonElement>("[data-close-invoice]").forEach((btn) => {
|
||||||
|
btn.addEventListener("click", () => dialog.close());
|
||||||
|
});
|
||||||
|
// Klick auf den abgedunkelten Hintergrund schließt den Dialog ebenfalls.
|
||||||
|
dialog.addEventListener("click", (e) => {
|
||||||
|
if (e.target === dialog) dialog.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Pro Bestellposition: Button "Rezension schreiben" durch "✓ Bewertet" ersetzen, sobald für
|
// Pro Bestellposition: Button "Rezension schreiben" durch "✓ Bewertet" ersetzen, sobald für
|
||||||
// genau diese Bestellung+Produkt schon eine Rezension existiert (siehe scripts/reviews.ts,
|
// genau diese Bestellung+Produkt schon eine Rezension existiert (siehe scripts/reviews.ts,
|
||||||
// wird beim Absenden des Formulars auf der Produktseite markiert).
|
// wird beim Absenden des Formulars auf der Produktseite markiert).
|
||||||
|
|||||||
@@ -141,13 +141,72 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
<span class="order-total">{t.accountDash.orderTotal}: <strong>{formatPrice(b.summe, lang)}</strong></span>
|
<span class="order-total">{t.accountDash.orderTotal}: <strong>{formatPrice(b.summe, lang)}</strong></span>
|
||||||
<div class="order-actions">
|
<div class="order-actions">
|
||||||
{b.tracking && <a class="btn btn-outline btn-sm" href={`https://www.dhl.de/de/privatkunden/dhl-sendungsverfolgung.html?piececode=${b.tracking}`} target="_blank" rel="noopener">{t.accountDash.trackingBtn}</a>}
|
{b.tracking && <a class="btn btn-outline btn-sm" href={`https://www.dhl.de/de/privatkunden/dhl-sendungsverfolgung.html?piececode=${b.tracking}`} target="_blank" rel="noopener">{t.accountDash.trackingBtn}</a>}
|
||||||
<a class="btn btn-outline btn-sm" href="#">{t.accountDash.invoiceBtn}</a>
|
<button type="button" class="btn btn-outline btn-sm" data-open-invoice={`invoice-${b.nummer}`}>{t.accountDash.invoiceBtn}</button>
|
||||||
<a class="btn btn-outline btn-sm" href="/en/shop/">{t.accountDash.reorderBtn}</a>
|
<a class="btn btn-outline btn-sm" href="/en/shop/">{t.accountDash.reorderBtn}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{b.tracking && (
|
{b.tracking && (
|
||||||
<p class="small order-tracking-no">{t.accountDash.trackingLabel}: <code>{b.tracking}</code></p>
|
<p class="small order-tracking-no">{t.accountDash.trackingLabel}: <code>{b.tracking}</code></p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Rechnung direkt auf der Seite ansehen (natives <dialog>, siehe Skript unten) —
|
||||||
|
kein Download nötig. Empfängername wird beim Öffnen live aus dem Konto befüllt
|
||||||
|
(siehe .invoice-billto-name), Adresse ist bewusst dieselbe Platzhalter-Adresse
|
||||||
|
wie oben unter "Meine Daten". */}
|
||||||
|
<dialog class="invoice-dialog" id={`invoice-${b.nummer}`}>
|
||||||
|
<div class="invoice-card">
|
||||||
|
<div class="invoice-head">
|
||||||
|
<div>
|
||||||
|
<h3>{t.accountDash.invoiceTitle}</h3>
|
||||||
|
<p class="invoice-meta">{t.accountDash.invoiceNumberLabel}: {b.nummer}</p>
|
||||||
|
<p class="invoice-meta">{t.accountDash.invoiceDateLabel}: {b.datum}</p>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="invoice-close" data-close-invoice aria-label={t.accountDash.invoiceCloseBtn}>✕</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="invoice-parties">
|
||||||
|
<div>
|
||||||
|
<h4>{t.accountDash.invoiceSellerLabel}</h4>
|
||||||
|
<p>Van's DIY & Bastelbedarf</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4>{t.accountDash.invoiceBillToLabel}</h4>
|
||||||
|
<p><span class="invoice-billto-name">–</span><br />Musterstraße 1<br />10115 Berlin<br />Deutschland</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="invoice-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{t.accountDash.invoiceItemLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceQtyLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceUnitPriceLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceSumLabel}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{b.artikel.map((a) => (
|
||||||
|
<tr>
|
||||||
|
<td>{a.name}</td>
|
||||||
|
<td>{a.menge}</td>
|
||||||
|
<td>{formatPrice(a.preis, lang)}</td>
|
||||||
|
<td>{formatPrice(a.preis * a.menge, lang)}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
<tr class="invoice-total-row">
|
||||||
|
<td colspan="3">{t.accountDash.orderTotal}</td>
|
||||||
|
<td>{formatPrice(b.summe, lang)}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="invoice-vat-note">{t.common.vatNote}</p>
|
||||||
|
|
||||||
|
<div class="invoice-foot">
|
||||||
|
<button type="button" class="btn btn-outline btn-sm" data-close-invoice>{t.accountDash.invoiceCloseBtn}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -316,6 +375,10 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
el.style.backgroundImage = bg;
|
el.style.backgroundImage = bg;
|
||||||
el.textContent = text;
|
el.textContent = text;
|
||||||
});
|
});
|
||||||
|
// Empfängername in allen (schon gerenderten) Rechnungs-Dialogen live mit aktualisieren.
|
||||||
|
document.querySelectorAll<HTMLElement>(".invoice-billto-name").forEach((el) => {
|
||||||
|
el.textContent = anzeigeName(a) || fallbackName;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
renderProfil();
|
renderProfil();
|
||||||
window.addEventListener("account:changed", renderProfil);
|
window.addEventListener("account:changed", renderProfil);
|
||||||
@@ -351,6 +414,25 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
window.location.href = loginPath;
|
window.location.href = loginPath;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Rechnung direkt auf der Seite ansehen: natives <dialog> pro Bestellung, geöffnet/geschlossen
|
||||||
|
// per Button — kein Download nötig, kein Verlassen der Seite.
|
||||||
|
document.querySelectorAll<HTMLButtonElement>("[data-open-invoice]").forEach((btn) => {
|
||||||
|
btn.addEventListener("click", () => {
|
||||||
|
const id = btn.dataset.openInvoice;
|
||||||
|
const dialog = id ? (document.getElementById(id) as HTMLDialogElement | null) : null;
|
||||||
|
dialog?.showModal();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document.querySelectorAll<HTMLDialogElement>(".invoice-dialog").forEach((dialog) => {
|
||||||
|
dialog.querySelectorAll<HTMLButtonElement>("[data-close-invoice]").forEach((btn) => {
|
||||||
|
btn.addEventListener("click", () => dialog.close());
|
||||||
|
});
|
||||||
|
// Klick auf den abgedunkelten Hintergrund schließt den Dialog ebenfalls.
|
||||||
|
dialog.addEventListener("click", (e) => {
|
||||||
|
if (e.target === dialog) dialog.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Pro Bestellposition: Button "Rezension schreiben" durch "✓ Bewertet" ersetzen, sobald für
|
// Pro Bestellposition: Button "Rezension schreiben" durch "✓ Bewertet" ersetzen, sobald für
|
||||||
// genau diese Bestellung+Produkt schon eine Rezension existiert (siehe scripts/reviews.ts,
|
// genau diese Bestellung+Produkt schon eine Rezension existiert (siehe scripts/reviews.ts,
|
||||||
// wird beim Absenden des Formulars auf der Produktseite markiert).
|
// wird beim Absenden des Formulars auf der Produktseite markiert).
|
||||||
|
|||||||
@@ -141,13 +141,72 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
<span class="order-total">{t.accountDash.orderTotal}: <strong>{formatPrice(b.summe, lang)}</strong></span>
|
<span class="order-total">{t.accountDash.orderTotal}: <strong>{formatPrice(b.summe, lang)}</strong></span>
|
||||||
<div class="order-actions">
|
<div class="order-actions">
|
||||||
{b.tracking && <a class="btn btn-outline btn-sm" href={`https://www.dhl.de/de/privatkunden/dhl-sendungsverfolgung.html?piececode=${b.tracking}`} target="_blank" rel="noopener">{t.accountDash.trackingBtn}</a>}
|
{b.tracking && <a class="btn btn-outline btn-sm" href={`https://www.dhl.de/de/privatkunden/dhl-sendungsverfolgung.html?piececode=${b.tracking}`} target="_blank" rel="noopener">{t.accountDash.trackingBtn}</a>}
|
||||||
<a class="btn btn-outline btn-sm" href="#">{t.accountDash.invoiceBtn}</a>
|
<button type="button" class="btn btn-outline btn-sm" data-open-invoice={`invoice-${b.nummer}`}>{t.accountDash.invoiceBtn}</button>
|
||||||
<a class="btn btn-outline btn-sm" href="/fr/shop/">{t.accountDash.reorderBtn}</a>
|
<a class="btn btn-outline btn-sm" href="/fr/shop/">{t.accountDash.reorderBtn}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{b.tracking && (
|
{b.tracking && (
|
||||||
<p class="small order-tracking-no">{t.accountDash.trackingLabel}: <code>{b.tracking}</code></p>
|
<p class="small order-tracking-no">{t.accountDash.trackingLabel}: <code>{b.tracking}</code></p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Rechnung direkt auf der Seite ansehen (natives <dialog>, siehe Skript unten) —
|
||||||
|
kein Download nötig. Empfängername wird beim Öffnen live aus dem Konto befüllt
|
||||||
|
(siehe .invoice-billto-name), Adresse ist bewusst dieselbe Platzhalter-Adresse
|
||||||
|
wie oben unter "Meine Daten". */}
|
||||||
|
<dialog class="invoice-dialog" id={`invoice-${b.nummer}`}>
|
||||||
|
<div class="invoice-card">
|
||||||
|
<div class="invoice-head">
|
||||||
|
<div>
|
||||||
|
<h3>{t.accountDash.invoiceTitle}</h3>
|
||||||
|
<p class="invoice-meta">{t.accountDash.invoiceNumberLabel}: {b.nummer}</p>
|
||||||
|
<p class="invoice-meta">{t.accountDash.invoiceDateLabel}: {b.datum}</p>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="invoice-close" data-close-invoice aria-label={t.accountDash.invoiceCloseBtn}>✕</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="invoice-parties">
|
||||||
|
<div>
|
||||||
|
<h4>{t.accountDash.invoiceSellerLabel}</h4>
|
||||||
|
<p>Van's DIY & Bastelbedarf</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4>{t.accountDash.invoiceBillToLabel}</h4>
|
||||||
|
<p><span class="invoice-billto-name">–</span><br />Musterstraße 1<br />10115 Berlin<br />Deutschland</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="invoice-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{t.accountDash.invoiceItemLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceQtyLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceUnitPriceLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceSumLabel}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{b.artikel.map((a) => (
|
||||||
|
<tr>
|
||||||
|
<td>{a.name}</td>
|
||||||
|
<td>{a.menge}</td>
|
||||||
|
<td>{formatPrice(a.preis, lang)}</td>
|
||||||
|
<td>{formatPrice(a.preis * a.menge, lang)}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
<tr class="invoice-total-row">
|
||||||
|
<td colspan="3">{t.accountDash.orderTotal}</td>
|
||||||
|
<td>{formatPrice(b.summe, lang)}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="invoice-vat-note">{t.common.vatNote}</p>
|
||||||
|
|
||||||
|
<div class="invoice-foot">
|
||||||
|
<button type="button" class="btn btn-outline btn-sm" data-close-invoice>{t.accountDash.invoiceCloseBtn}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -316,6 +375,10 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
el.style.backgroundImage = bg;
|
el.style.backgroundImage = bg;
|
||||||
el.textContent = text;
|
el.textContent = text;
|
||||||
});
|
});
|
||||||
|
// Empfängername in allen (schon gerenderten) Rechnungs-Dialogen live mit aktualisieren.
|
||||||
|
document.querySelectorAll<HTMLElement>(".invoice-billto-name").forEach((el) => {
|
||||||
|
el.textContent = anzeigeName(a) || fallbackName;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
renderProfil();
|
renderProfil();
|
||||||
window.addEventListener("account:changed", renderProfil);
|
window.addEventListener("account:changed", renderProfil);
|
||||||
@@ -351,6 +414,25 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
window.location.href = loginPath;
|
window.location.href = loginPath;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Rechnung direkt auf der Seite ansehen: natives <dialog> pro Bestellung, geöffnet/geschlossen
|
||||||
|
// per Button — kein Download nötig, kein Verlassen der Seite.
|
||||||
|
document.querySelectorAll<HTMLButtonElement>("[data-open-invoice]").forEach((btn) => {
|
||||||
|
btn.addEventListener("click", () => {
|
||||||
|
const id = btn.dataset.openInvoice;
|
||||||
|
const dialog = id ? (document.getElementById(id) as HTMLDialogElement | null) : null;
|
||||||
|
dialog?.showModal();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document.querySelectorAll<HTMLDialogElement>(".invoice-dialog").forEach((dialog) => {
|
||||||
|
dialog.querySelectorAll<HTMLButtonElement>("[data-close-invoice]").forEach((btn) => {
|
||||||
|
btn.addEventListener("click", () => dialog.close());
|
||||||
|
});
|
||||||
|
// Klick auf den abgedunkelten Hintergrund schließt den Dialog ebenfalls.
|
||||||
|
dialog.addEventListener("click", (e) => {
|
||||||
|
if (e.target === dialog) dialog.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Pro Bestellposition: Button "Rezension schreiben" durch "✓ Bewertet" ersetzen, sobald für
|
// Pro Bestellposition: Button "Rezension schreiben" durch "✓ Bewertet" ersetzen, sobald für
|
||||||
// genau diese Bestellung+Produkt schon eine Rezension existiert (siehe scripts/reviews.ts,
|
// genau diese Bestellung+Produkt schon eine Rezension existiert (siehe scripts/reviews.ts,
|
||||||
// wird beim Absenden des Formulars auf der Produktseite markiert).
|
// wird beim Absenden des Formulars auf der Produktseite markiert).
|
||||||
|
|||||||
@@ -141,13 +141,72 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
<span class="order-total">{t.accountDash.orderTotal}: <strong>{formatPrice(b.summe, lang)}</strong></span>
|
<span class="order-total">{t.accountDash.orderTotal}: <strong>{formatPrice(b.summe, lang)}</strong></span>
|
||||||
<div class="order-actions">
|
<div class="order-actions">
|
||||||
{b.tracking && <a class="btn btn-outline btn-sm" href={`https://www.dhl.de/de/privatkunden/dhl-sendungsverfolgung.html?piececode=${b.tracking}`} target="_blank" rel="noopener">{t.accountDash.trackingBtn}</a>}
|
{b.tracking && <a class="btn btn-outline btn-sm" href={`https://www.dhl.de/de/privatkunden/dhl-sendungsverfolgung.html?piececode=${b.tracking}`} target="_blank" rel="noopener">{t.accountDash.trackingBtn}</a>}
|
||||||
<a class="btn btn-outline btn-sm" href="#">{t.accountDash.invoiceBtn}</a>
|
<button type="button" class="btn btn-outline btn-sm" data-open-invoice={`invoice-${b.nummer}`}>{t.accountDash.invoiceBtn}</button>
|
||||||
<a class="btn btn-outline btn-sm" href="/shop/">{t.accountDash.reorderBtn}</a>
|
<a class="btn btn-outline btn-sm" href="/shop/">{t.accountDash.reorderBtn}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{b.tracking && (
|
{b.tracking && (
|
||||||
<p class="small order-tracking-no">{t.accountDash.trackingLabel}: <code>{b.tracking}</code></p>
|
<p class="small order-tracking-no">{t.accountDash.trackingLabel}: <code>{b.tracking}</code></p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Rechnung direkt auf der Seite ansehen (natives <dialog>, siehe Skript unten) —
|
||||||
|
kein Download nötig. Empfängername wird beim Öffnen live aus dem Konto befüllt
|
||||||
|
(siehe .invoice-billto-name), Adresse ist bewusst dieselbe Platzhalter-Adresse
|
||||||
|
wie oben unter "Meine Daten". */}
|
||||||
|
<dialog class="invoice-dialog" id={`invoice-${b.nummer}`}>
|
||||||
|
<div class="invoice-card">
|
||||||
|
<div class="invoice-head">
|
||||||
|
<div>
|
||||||
|
<h3>{t.accountDash.invoiceTitle}</h3>
|
||||||
|
<p class="invoice-meta">{t.accountDash.invoiceNumberLabel}: {b.nummer}</p>
|
||||||
|
<p class="invoice-meta">{t.accountDash.invoiceDateLabel}: {b.datum}</p>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="invoice-close" data-close-invoice aria-label={t.accountDash.invoiceCloseBtn}>✕</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="invoice-parties">
|
||||||
|
<div>
|
||||||
|
<h4>{t.accountDash.invoiceSellerLabel}</h4>
|
||||||
|
<p>Van's DIY & Bastelbedarf</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4>{t.accountDash.invoiceBillToLabel}</h4>
|
||||||
|
<p><span class="invoice-billto-name">–</span><br />Musterstraße 1<br />10115 Berlin<br />Deutschland</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="invoice-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{t.accountDash.invoiceItemLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceQtyLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceUnitPriceLabel}</th>
|
||||||
|
<th>{t.accountDash.invoiceSumLabel}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{b.artikel.map((a) => (
|
||||||
|
<tr>
|
||||||
|
<td>{a.name}</td>
|
||||||
|
<td>{a.menge}</td>
|
||||||
|
<td>{formatPrice(a.preis, lang)}</td>
|
||||||
|
<td>{formatPrice(a.preis * a.menge, lang)}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
<tr class="invoice-total-row">
|
||||||
|
<td colspan="3">{t.accountDash.orderTotal}</td>
|
||||||
|
<td>{formatPrice(b.summe, lang)}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="invoice-vat-note">{t.common.vatNote}</p>
|
||||||
|
|
||||||
|
<div class="invoice-foot">
|
||||||
|
<button type="button" class="btn btn-outline btn-sm" data-close-invoice>{t.accountDash.invoiceCloseBtn}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -316,6 +375,10 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
el.style.backgroundImage = bg;
|
el.style.backgroundImage = bg;
|
||||||
el.textContent = text;
|
el.textContent = text;
|
||||||
});
|
});
|
||||||
|
// Empfängername in allen (schon gerenderten) Rechnungs-Dialogen live mit aktualisieren.
|
||||||
|
document.querySelectorAll<HTMLElement>(".invoice-billto-name").forEach((el) => {
|
||||||
|
el.textContent = anzeigeName(a) || fallbackName;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
renderProfil();
|
renderProfil();
|
||||||
window.addEventListener("account:changed", renderProfil);
|
window.addEventListener("account:changed", renderProfil);
|
||||||
@@ -351,6 +414,25 @@ const offeneSendungen = beispielBestellungen.filter((b) => b.status === "versend
|
|||||||
window.location.href = loginPath;
|
window.location.href = loginPath;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Rechnung direkt auf der Seite ansehen: natives <dialog> pro Bestellung, geöffnet/geschlossen
|
||||||
|
// per Button — kein Download nötig, kein Verlassen der Seite.
|
||||||
|
document.querySelectorAll<HTMLButtonElement>("[data-open-invoice]").forEach((btn) => {
|
||||||
|
btn.addEventListener("click", () => {
|
||||||
|
const id = btn.dataset.openInvoice;
|
||||||
|
const dialog = id ? (document.getElementById(id) as HTMLDialogElement | null) : null;
|
||||||
|
dialog?.showModal();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document.querySelectorAll<HTMLDialogElement>(".invoice-dialog").forEach((dialog) => {
|
||||||
|
dialog.querySelectorAll<HTMLButtonElement>("[data-close-invoice]").forEach((btn) => {
|
||||||
|
btn.addEventListener("click", () => dialog.close());
|
||||||
|
});
|
||||||
|
// Klick auf den abgedunkelten Hintergrund schließt den Dialog ebenfalls.
|
||||||
|
dialog.addEventListener("click", (e) => {
|
||||||
|
if (e.target === dialog) dialog.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Pro Bestellposition: Button "Rezension schreiben" durch "✓ Bewertet" ersetzen, sobald für
|
// Pro Bestellposition: Button "Rezension schreiben" durch "✓ Bewertet" ersetzen, sobald für
|
||||||
// genau diese Bestellung+Produkt schon eine Rezension existiert (siehe scripts/reviews.ts,
|
// genau diese Bestellung+Produkt schon eine Rezension existiert (siehe scripts/reviews.ts,
|
||||||
// wird beim Absenden des Formulars auf der Produktseite markiert).
|
// wird beim Absenden des Formulars auf der Produktseite markiert).
|
||||||
|
|||||||
@@ -1556,6 +1556,56 @@ a:focus-visible, button:focus-visible {
|
|||||||
.order-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
|
.order-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
|
||||||
.order-tracking-no { margin: 0; color: var(--c-text-muted); }
|
.order-tracking-no { margin: 0; color: var(--c-text-muted); }
|
||||||
.order-tracking-no code { font-size: 0.9em; letter-spacing: 0.02em; }
|
.order-tracking-no code { font-size: 0.9em; letter-spacing: 0.02em; }
|
||||||
|
|
||||||
|
/* Rechnung direkt auf der Seite ansehen (natives <dialog>) — kein Download nötig, öffnet sich
|
||||||
|
sofort als Overlay über der aktuellen Ansicht. */
|
||||||
|
.invoice-dialog {
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--c-text);
|
||||||
|
max-width: min(94vw, 580px);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.invoice-dialog::backdrop { background: rgba(6, 5, 10, 0.75); backdrop-filter: blur(3px); }
|
||||||
|
.invoice-card {
|
||||||
|
background: linear-gradient(165deg, var(--c-anthracite-light), var(--c-anthracite));
|
||||||
|
border: 1.5px solid rgba(244, 241, 247, 0.16);
|
||||||
|
border-radius: var(--radius-l);
|
||||||
|
padding: 1.8rem;
|
||||||
|
max-height: 85vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
box-shadow: var(--shadow-card);
|
||||||
|
}
|
||||||
|
.invoice-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; margin-bottom: 1rem; }
|
||||||
|
.invoice-head h3 { margin: 0; }
|
||||||
|
.invoice-meta { margin: 0.3rem 0 0; font-size: 0.88rem; color: var(--c-text-muted); }
|
||||||
|
.invoice-close {
|
||||||
|
background: none;
|
||||||
|
border: 1px solid rgba(244, 241, 247, 0.2);
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
color: var(--c-text);
|
||||||
|
cursor: pointer;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
.invoice-close:hover { border-color: var(--c-accent); color: var(--c-accent); }
|
||||||
|
.invoice-parties { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; margin: 1.3rem 0; }
|
||||||
|
.invoice-parties h4 { margin: 0 0 0.35em; font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--c-accent); }
|
||||||
|
.invoice-parties p { margin: 0; font-size: 0.9rem; color: var(--c-text-muted); line-height: 1.55; }
|
||||||
|
@media (max-width: 480px) { .invoice-parties { grid-template-columns: 1fr; } }
|
||||||
|
.invoice-table { width: 100%; border-collapse: collapse; margin-top: 0.6rem; }
|
||||||
|
.invoice-table th, .invoice-table td { text-align: left; padding: 0.55em 0.35em; border-bottom: 1px solid rgba(244, 241, 247, 0.1); font-size: 0.9rem; }
|
||||||
|
.invoice-table th { color: var(--c-text-muted); font-weight: 600; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.04em; }
|
||||||
|
.invoice-table th:last-child, .invoice-table td:last-child,
|
||||||
|
.invoice-table th:nth-child(2), .invoice-table td:nth-child(2),
|
||||||
|
.invoice-table th:nth-child(3), .invoice-table td:nth-child(3) { text-align: right; }
|
||||||
|
.invoice-total-row td { font-weight: 700; color: var(--c-accent); border-bottom: none; padding-top: 0.8em; font-size: 1rem; }
|
||||||
|
.invoice-vat-note { margin: 1.1rem 0 0; font-size: 0.8rem; color: var(--c-text-muted); }
|
||||||
|
.invoice-foot { display: flex; justify-content: flex-end; margin-top: 1.4rem; }
|
||||||
.profile-card { display: flex; flex-direction: column; align-items: stretch; gap: 1.3rem; }
|
.profile-card { display: flex; flex-direction: column; align-items: stretch; gap: 1.3rem; }
|
||||||
.profile-card .specs { margin-top: 0; width: 100%; }
|
.profile-card .specs { margin-top: 0; width: 100%; }
|
||||||
.profile-photo-row { display: flex; align-items: center; gap: 1.1rem; }
|
.profile-photo-row { display: flex; align-items: center; gap: 1.1rem; }
|
||||||
|
|||||||
Reference in New Issue
Block a user