feat: add 30-day money back guarantee trust badge above complete order button

- Add green trust badge with checkmark icon above 'Complete Order' button
- Add translations for all locales (EN, SR, DE, FR)
- Badge includes: '30-Day Money-Back Guarantee' text
- Styled with green background and border to match trust/conversion theme
This commit is contained in:
Unchained
2026-03-29 14:27:05 +02:00
parent eaf599f248
commit 10b18c6010
8 changed files with 62 additions and 81 deletions

View File

@@ -38,9 +38,9 @@ export function PaymentSection({
disabled={disabled}
/>
{/* Show COD instructions when COD is selected */}
{/* COD instructions can be shown here if needed */}
{selectedMethod?.id === "cod" && (
<CODInstructions locale={locale} />
<CODInstructions />
)}
</section>
);

View File

@@ -709,6 +709,14 @@ export default function CheckoutPage() {
disabled={isLoading}
/>
{/* Money Back Guarantee Trust Badge */}
<div className="flex items-center justify-center gap-2 py-3 px-4 bg-green-50 rounded-lg border border-green-100">
<svg className="w-5 h-5 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span className="text-sm font-medium text-green-800">{t("moneyBackGuarantee")}</span>
</div>
<button
type="submit"
disabled={isLoading || lines.length === 0 || !selectedShippingMethod}

View File

@@ -1,55 +1,6 @@
"use client";
// COD Instructions component - currently disabled as the instructions are self-explanatory
// Can be re-enabled if payment method instructions are needed in the future
import { useTranslations } from "next-intl";
import { Banknote, Package, CheckCircle } from "lucide-react";
interface CODInstructionsProps {
locale: string;
}
export function CODInstructions({ locale }: CODInstructionsProps) {
const t = useTranslations("Payment.cod");
const instructions = [
{
icon: Banknote,
title: t("instructions.prepareCash"),
description: t("instructions.prepareCashDesc"),
},
{
icon: Package,
title: t("instructions.inspectOrder"),
description: t("instructions.inspectOrderDesc"),
},
{
icon: CheckCircle,
title: t("instructions.noFee"),
description: t("instructions.noFeeDesc"),
},
];
return (
<div className="mt-4 rounded-lg bg-blue-50 p-4">
<h4 className="mb-3 font-medium text-blue-900">
{t("instructions.title")}
</h4>
<div className="space-y-3">
{instructions.map((instruction, index) => {
const Icon = instruction.icon;
return (
<div key={index} className="flex items-start gap-3">
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-blue-100">
<Icon className="h-4 w-4 text-blue-600" />
</div>
<div>
<p className="font-medium text-blue-900">{instruction.title}</p>
<p className="text-sm text-blue-700">{instruction.description}</p>
</div>
</div>
);
})}
</div>
</div>
);
}
export function CODInstructions() {
return null;
}

View File

@@ -37,11 +37,11 @@ export function PaymentMethodCard({
return (
<label
className={cn(
"relative flex cursor-pointer items-start gap-3 rounded-lg border-2 p-4 transition-all duration-200",
"hover:shadow-md",
"relative flex cursor-pointer items-start gap-4 rounded-xl border-2 p-5 transition-all duration-300",
"hover:scale-[1.02] hover:shadow-lg",
isSelected
? "border-black bg-white shadow-lg ring-1 ring-black/5"
: "border-gray-200 bg-white hover:border-gray-300",
? "border-[#059669] bg-white shadow-xl shadow-[#047857]/30"
: "border-gray-200 bg-white hover:border-[#3B82F6]",
(disabled || !method.available) && "cursor-not-allowed opacity-50"
)}
>
@@ -55,23 +55,50 @@ export function PaymentMethodCard({
className="sr-only"
/>
{/* Glowing green checkmark for selected */}
{isSelected && (
<div className="absolute -right-2 -top-2 z-10">
<div className="relative">
{/* Glow effect */}
<div className="absolute inset-0 rounded-full bg-[#059669] blur-md opacity-70" />
{/* Green circle with checkmark */}
<div className="relative flex h-8 w-8 items-center justify-center rounded-full bg-gradient-to-br from-[#059669] to-[#047857] shadow-lg">
<svg
className="h-5 w-5 text-white"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={3}
>
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
</svg>
</div>
</div>
</div>
)}
<div className={cn(
"flex h-10 w-10 shrink-0 items-center justify-center rounded-full transition-colors",
isSelected ? "bg-black text-white" : "bg-gray-100 text-gray-600"
"flex h-12 w-12 shrink-0 items-center justify-center rounded-xl transition-all duration-300",
isSelected
? "bg-gradient-to-br from-[#059669] to-[#047857] shadow-lg shadow-[#047857]/40"
: "bg-gradient-to-br from-blue-50 to-blue-100"
)}>
{Icon && <Icon className="h-5 w-5" />}
<Icon className={cn(
"h-6 w-6 transition-colors",
isSelected ? "text-white" : "text-[#3B82F6]"
)} />
</div>
<div className="flex-1">
<div className="flex-1 pr-8">
<div className="flex items-center justify-between">
<span className={cn(
"font-semibold transition-colors",
isSelected ? "text-black" : "text-gray-900"
"text-lg font-bold transition-colors",
isSelected ? "text-[#047857]" : "text-gray-900"
)}>
{translatedName}
</span>
{method.fee > 0 && (
<span className="text-sm text-amber-600">
<span className="text-sm font-semibold text-amber-600 bg-amber-100 px-2 py-1 rounded-full">
+{new Intl.NumberFormat(locale === 'sr' ? 'sr-RS' : 'en-US', {
style: 'currency',
currency: 'RSD',
@@ -81,26 +108,17 @@ export function PaymentMethodCard({
</div>
<p className={cn(
"mt-1 text-sm",
"mt-1 text-sm font-medium transition-colors",
isSelected ? "text-gray-700" : "text-gray-600"
)}>{translatedDescription}</p>
)}>
{translatedDescription}
</p>
{!method.available && (
<span className="mt-2 inline-block text-xs text-gray-500">
<span className="mt-2 inline-block text-xs font-medium text-gray-500 bg-gray-100 px-2 py-1 rounded">
{t(`${method.id}.comingSoon`)}
</span>
)}
{isSelected && (
<div className="absolute right-4 top-4">
<span className="inline-flex items-center gap-1 rounded-full bg-black px-3 py-1 text-xs font-medium text-white">
<svg className="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}>
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
</svg>
{t("selected")}
</span>
</div>
)}
</div>
</label>
);

View File

@@ -361,6 +361,7 @@
"cashOnDeliveryDesc": "Bezahlen Sie, wenn Ihre Bestellung an Ihre Tür geliefert wird.",
"processing": "Wird bearbeitet...",
"completeOrder": "Bestellung abschließen - {total}",
"moneyBackGuarantee": "30 Tage Geld-zurück-Garantie",
"orderSummary": "Bestellübersicht",
"qty": "Menge",
"subtotal": "Zwischensumme",

View File

@@ -407,6 +407,7 @@
"cashOnDeliveryDesc": "Pay when your order is delivered to your door.",
"processing": "Processing...",
"completeOrder": "Complete Order - {total}",
"moneyBackGuarantee": "30-Day Money-Back Guarantee",
"orderSummary": "Order Summary",
"qty": "Qty",
"subtotal": "Subtotal",

View File

@@ -361,6 +361,7 @@
"cashOnDeliveryDesc": "Payez lorsque votre commande est livrée à votre porte.",
"processing": "En cours...",
"completeOrder": "Finaliser la Commande - {total}",
"moneyBackGuarantee": "Garantie de remboursement de 30 jours",
"orderSummary": "Résumé de la Commande",
"qty": "Qté",
"subtotal": "Sous-total",

View File

@@ -407,6 +407,7 @@
"cashOnDeliveryDesc": "Platite kada vam narudžbina bude isporučena na vrata.",
"processing": "Obrađivanje...",
"completeOrder": "Završi narudžbinu - {total}",
"moneyBackGuarantee": "30-dnevna garancija povrata novca",
"orderSummary": "Pregled narudžbine",
"qty": "Kol",
"subtotal": "Ukupno",