This commit is contained in:
@@ -5,6 +5,7 @@ import { motion, AnimatePresence } from "framer-motion";
|
||||
import { X, KeyRound, Building2, User, Mail, LogOut, ShieldCheck, Sparkles, Loader2, Lock } from "lucide-react";
|
||||
import { loginClient, registerClientRequest, logoutClient, updateClientPassword } from "@/app/actions/clientAuth";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export default function AuthModal({ session }: { session: any }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
@@ -13,6 +14,7 @@ export default function AuthModal({ session }: { session: any }) {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [success, setSuccess] = useState<string | null>(null);
|
||||
const router = useRouter();
|
||||
const t = useTranslations("AuthModal");
|
||||
|
||||
useEffect(() => {
|
||||
const handleOpen = (e: Event) => {
|
||||
@@ -57,7 +59,7 @@ export default function AuthModal({ session }: { session: any }) {
|
||||
if (res.error) {
|
||||
setError(res.error);
|
||||
} else {
|
||||
setSuccess("Access requested successfully. We will notify you via email upon engineering approval.");
|
||||
setSuccess(t("successMessage"));
|
||||
form.reset();
|
||||
}
|
||||
setIsLoading(false);
|
||||
@@ -75,7 +77,7 @@ export default function AuthModal({ session }: { session: any }) {
|
||||
if (res.error) {
|
||||
setError(res.error);
|
||||
} else {
|
||||
setSuccess("Password updated securely.");
|
||||
setSuccess(t("passwordUpdated"));
|
||||
form.reset();
|
||||
}
|
||||
setIsLoading(false);
|
||||
@@ -104,7 +106,6 @@ export default function AuthModal({ session }: { session: any }) {
|
||||
exit={{ opacity: 0, scale: 0.95 }}
|
||||
className="relative w-full max-w-md bg-white dark:bg-[#111] rounded-[2rem] shadow-2xl overflow-hidden border border-black/5 dark:border-white/10"
|
||||
>
|
||||
{/* 🔥 FIX: Z-INDEX 100 PARA EVITAR BLOQUEOS */}
|
||||
<button
|
||||
onClick={() => setIsOpen(false)}
|
||||
className="absolute top-4 right-4 p-2 bg-black/5 dark:bg-white/10 hover:bg-black/10 dark:hover:bg-white/20 rounded-full transition-colors z-[100]"
|
||||
@@ -120,13 +121,13 @@ export default function AuthModal({ session }: { session: any }) {
|
||||
</div>
|
||||
|
||||
<h2 className="text-2xl font-light text-[#1D1D1F] dark:text-white relative z-10 flex items-center justify-center gap-2">
|
||||
<Lock size={20} className="text-[#86868B]" /> B2B Portal
|
||||
<Lock size={20} className="text-[#86868B]" /> {t("b2bPortal")}
|
||||
</h2>
|
||||
|
||||
{!session && (
|
||||
<div className="flex bg-black/5 dark:bg-white/5 rounded-xl p-1 mt-6 relative z-10">
|
||||
<button onClick={() => {setMode("LOGIN"); setError(null); setSuccess(null);}} className={`flex-1 py-2 text-xs font-semibold rounded-lg transition-all ${mode === "LOGIN" ? "bg-white dark:bg-[#1D1D1F] shadow text-[#1D1D1F] dark:text-white" : "text-[#86868B]"}`}>Sign In</button>
|
||||
<button onClick={() => {setMode("REGISTER"); setError(null); setSuccess(null);}} className={`flex-1 py-2 text-xs font-semibold rounded-lg transition-all ${mode === "REGISTER" ? "bg-white dark:bg-[#1D1D1F] shadow text-[#1D1D1F] dark:text-white" : "text-[#86868B]"}`}>Request Access</button>
|
||||
<button onClick={() => {setMode("LOGIN"); setError(null); setSuccess(null);}} className={`flex-1 py-2 text-xs font-semibold rounded-lg transition-all ${mode === "LOGIN" ? "bg-white dark:bg-[#1D1D1F] shadow text-[#1D1D1F] dark:text-white" : "text-[#86868B]"}`}>{t("signIn")}</button>
|
||||
<button onClick={() => {setMode("REGISTER"); setError(null); setSuccess(null);}} className={`flex-1 py-2 text-xs font-semibold rounded-lg transition-all ${mode === "REGISTER" ? "bg-white dark:bg-[#1D1D1F] shadow text-[#1D1D1F] dark:text-white" : "text-[#86868B]"}`}>{t("requestAccess")}</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -138,15 +139,15 @@ export default function AuthModal({ session }: { session: any }) {
|
||||
{mode === "LOGIN" && !session && (
|
||||
<form onSubmit={handleLogin} className="space-y-4">
|
||||
<div>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><Mail size={12}/> Corporate Email</label>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><Mail size={12}/> {t("corporateEmail")}</label>
|
||||
<input name="email" type="email" required className="w-full bg-black/5 dark:bg-white/5 border border-transparent focus:border-[#0066CC] rounded-xl px-4 py-3 text-sm outline-none text-[#1D1D1F] dark:text-white transition-colors" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><KeyRound size={12}/> Password</label>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><KeyRound size={12}/> {t("password")}</label>
|
||||
<input name="password" type="password" required className="w-full bg-black/5 dark:bg-white/5 border border-transparent focus:border-[#0066CC] rounded-xl px-4 py-3 text-sm outline-none text-[#1D1D1F] dark:text-white transition-colors" />
|
||||
</div>
|
||||
<button disabled={isLoading} className="w-full mt-2 bg-[#1D1D1F] dark:bg-white text-white dark:text-black py-3.5 rounded-xl text-sm font-semibold flex justify-center items-center gap-2 active:scale-[0.98] transition-transform">
|
||||
{isLoading ? <Loader2 size={16} className="animate-spin" /> : "Access Secure Portal"}
|
||||
{isLoading ? <Loader2 size={16} className="animate-spin" /> : t("accessPortal")}
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
@@ -154,23 +155,23 @@ export default function AuthModal({ session }: { session: any }) {
|
||||
{mode === "REGISTER" && !session && (
|
||||
<form onSubmit={handleRegister} className="space-y-3">
|
||||
<div>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><User size={12}/> Full Name</label>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><User size={12}/> {t("fullName")}</label>
|
||||
<input name="fullName" required className="w-full bg-black/5 dark:bg-white/5 border border-transparent focus:border-[#0066CC] rounded-xl px-4 py-2.5 text-sm outline-none text-[#1D1D1F] dark:text-white transition-colors" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><Building2 size={12}/> Company Name</label>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><Building2 size={12}/> {t("companyName")}</label>
|
||||
<input name="companyName" required className="w-full bg-black/5 dark:bg-white/5 border border-transparent focus:border-[#0066CC] rounded-xl px-4 py-2.5 text-sm outline-none text-[#1D1D1F] dark:text-white transition-colors" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><Mail size={12}/> Work Email</label>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><Mail size={12}/> {t("workEmail")}</label>
|
||||
<input name="email" type="email" required className="w-full bg-black/5 dark:bg-white/5 border border-transparent focus:border-[#0066CC] rounded-xl px-4 py-2.5 text-sm outline-none text-[#1D1D1F] dark:text-white transition-colors" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><KeyRound size={12}/> Create Password</label>
|
||||
<label className="text-[10px] font-bold uppercase tracking-widest text-[#86868B] mb-1 flex items-center gap-1.5"><KeyRound size={12}/> {t("createPassword")}</label>
|
||||
<input name="password" type="password" required className="w-full bg-black/5 dark:bg-white/5 border border-transparent focus:border-[#0066CC] rounded-xl px-4 py-2.5 text-sm outline-none text-[#1D1D1F] dark:text-white transition-colors" />
|
||||
</div>
|
||||
<button disabled={isLoading} className="w-full mt-4 bg-[#1D1D1F] dark:bg-white text-white dark:text-black py-3.5 rounded-xl text-sm font-semibold flex justify-center items-center gap-2 active:scale-[0.98] transition-transform">
|
||||
{isLoading ? <Loader2 size={16} className="animate-spin" /> : "Submit Request"}
|
||||
{isLoading ? <Loader2 size={16} className="animate-spin" /> : t("submitRequest")}
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
@@ -188,15 +189,15 @@ export default function AuthModal({ session }: { session: any }) {
|
||||
</div>
|
||||
</div>
|
||||
<form onSubmit={handleChangePassword} className="space-y-3 pt-4 border-t border-black/5 dark:border-white/10">
|
||||
<h3 className="text-xs font-semibold text-[#1D1D1F] dark:text-white mb-2">Update Security Credentials</h3>
|
||||
<input name="currentPassword" type="password" placeholder="Current Password" required className="w-full bg-black/5 dark:bg-white/5 border border-transparent focus:border-[#0066CC] rounded-xl px-4 py-2.5 text-sm outline-none text-[#1D1D1F] dark:text-white transition-colors" />
|
||||
<input name="newPassword" type="password" placeholder="New Password" required minLength={8} className="w-full bg-black/5 dark:bg-white/5 border border-transparent focus:border-[#0066CC] rounded-xl px-4 py-2.5 text-sm outline-none text-[#1D1D1F] dark:text-white transition-colors" />
|
||||
<h3 className="text-xs font-semibold text-[#1D1D1F] dark:text-white mb-2">{t("updateCredentials")}</h3>
|
||||
<input name="currentPassword" type="password" placeholder={t("currentPassword")} required className="w-full bg-black/5 dark:bg-white/5 border border-transparent focus:border-[#0066CC] rounded-xl px-4 py-2.5 text-sm outline-none text-[#1D1D1F] dark:text-white transition-colors" />
|
||||
<input name="newPassword" type="password" placeholder={t("newPassword")} required minLength={8} className="w-full bg-black/5 dark:bg-white/5 border border-transparent focus:border-[#0066CC] rounded-xl px-4 py-2.5 text-sm outline-none text-[#1D1D1F] dark:text-white transition-colors" />
|
||||
<button disabled={isLoading} className="w-full bg-black/5 dark:bg-white/10 hover:bg-black/10 text-[#1D1D1F] dark:text-white py-2.5 rounded-xl text-sm font-medium transition-colors">
|
||||
{isLoading ? <Loader2 size={16} className="animate-spin mx-auto" /> : "Change Password"}
|
||||
{isLoading ? <Loader2 size={16} className="animate-spin mx-auto" /> : t("changePassword")}
|
||||
</button>
|
||||
</form>
|
||||
<button onClick={handleLogout} className="w-full flex items-center justify-center gap-2 text-rose-500 hover:bg-rose-500/10 py-3.5 rounded-xl text-sm font-semibold transition-colors">
|
||||
<LogOut size={16}/> Secure Logout
|
||||
<LogOut size={16}/> {t("secureLogout")}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -16,7 +16,7 @@ interface ComponentGridProps {
|
||||
currentPage: number;
|
||||
totalPages: number;
|
||||
totalItems: number;
|
||||
session: any | null; // 🔥 LA SESIÓN DETERMINA TODO
|
||||
session: any | null;
|
||||
}
|
||||
|
||||
export default function ComponentGrid({ initialParts, locale, query, currentPage, totalPages, totalItems, session }: ComponentGridProps) {
|
||||
@@ -33,7 +33,7 @@ export default function ComponentGrid({ initialParts, locale, query, currentPage
|
||||
|
||||
useEffect(() => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (searchTerm !== query && session) { // Solo busca si hay sesión
|
||||
if (searchTerm !== query && session) {
|
||||
const params = new URLSearchParams(searchParams.toString());
|
||||
if (searchTerm) { params.set('q', searchTerm); params.set('page', '1'); }
|
||||
else { params.delete('q'); }
|
||||
@@ -57,7 +57,6 @@ export default function ComponentGrid({ initialParts, locale, query, currentPage
|
||||
router.push(`${pathname}?${params.toString()}`);
|
||||
};
|
||||
|
||||
// 🔥 EVENTO PARA ABRIR MODAL
|
||||
const openAuth = (mode: "LOGIN" | "REGISTER") => {
|
||||
window.dispatchEvent(new CustomEvent('flux:open-auth', { detail: { mode } }));
|
||||
};
|
||||
@@ -66,48 +65,48 @@ export default function ComponentGrid({ initialParts, locale, query, currentPage
|
||||
<>
|
||||
<AuthModal session={session} />
|
||||
|
||||
{/* 🔥 BOTÓN FLOTANTE DE PERFIL / LOGIN (Arriba a la derecha) */}
|
||||
{/* Floating profile / login button */}
|
||||
<div className="absolute top-32 right-6 md:right-12 z-50">
|
||||
<button
|
||||
onClick={() => window.dispatchEvent(new CustomEvent('flux:open-auth'))}
|
||||
className="flex items-center gap-2 px-4 py-2 bg-white dark:bg-[#111] border border-black/10 dark:border-white/10 rounded-full text-sm font-medium text-[#1D1D1F] dark:text-white shadow-sm hover:shadow-md transition-all"
|
||||
>
|
||||
{session ? <><UserCircle size={16}/> {session.name}</> : <><Lock size={16}/> B2B Login</>}
|
||||
{session ? <><UserCircle size={16}/> {session.name}</> : <><Lock size={16}/> {t("b2bLogin")}</>}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* 🛑 ESTADO BLOQUEADO (Visitantes sin sesión) */}
|
||||
{/* Locked state (visitors without session) */}
|
||||
{!session ? (
|
||||
<div className="mt-8 py-24 flex flex-col items-center justify-center text-center border border-dashed border-black/10 dark:border-white/10 rounded-[2rem] bg-white/30 dark:bg-[#111]/30">
|
||||
<div className="w-20 h-20 bg-black/5 dark:bg-white/5 rounded-full flex items-center justify-center mb-6">
|
||||
<Lock size={32} className="text-[#1D1D1F] dark:text-white" />
|
||||
</div>
|
||||
<h3 className="text-2xl font-light text-[#1D1D1F] dark:text-white mb-3">Access Restricted</h3>
|
||||
<h3 className="text-2xl font-light text-[#1D1D1F] dark:text-white mb-3">{t("accessRestricted")}</h3>
|
||||
<p className="text-[#86868B] max-w-md mx-auto mb-8">
|
||||
The FLUX Component Matrix is an exclusive B2B portal. Please sign in with your corporate account or request access to view components, pricing, and technical datasheets.
|
||||
{t("accessDescription")}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4">
|
||||
<button onClick={() => openAuth("LOGIN")} className="px-8 py-3.5 rounded-xl text-sm font-semibold bg-[#1D1D1F] dark:bg-white text-white dark:text-black flex items-center justify-center gap-2 transition-transform active:scale-95"><KeyRound size={16}/> Sign In</button>
|
||||
<button onClick={() => openAuth("REGISTER")} className="px-8 py-3.5 rounded-xl text-sm font-semibold bg-black/5 dark:bg-white/10 text-[#1D1D1F] dark:text-white hover:bg-black/10 dark:hover:bg-white/20 transition-all active:scale-95">Request Access</button>
|
||||
<button onClick={() => openAuth("LOGIN")} className="px-8 py-3.5 rounded-xl text-sm font-semibold bg-[#1D1D1F] dark:bg-white text-white dark:text-black flex items-center justify-center gap-2 transition-transform active:scale-95"><KeyRound size={16}/> {t("signIn")}</button>
|
||||
<button onClick={() => openAuth("REGISTER")} className="px-8 py-3.5 rounded-xl text-sm font-semibold bg-black/5 dark:bg-white/10 text-[#1D1D1F] dark:text-white hover:bg-black/10 dark:hover:bg-white/20 transition-all active:scale-95">{t("requestAccess")}</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
/* ✅ ESTADO DESBLOQUEADO (Catálogo Completo) */
|
||||
/* Unlocked state (full catalog) */
|
||||
<>
|
||||
<div className="flex flex-col md:flex-row justify-between items-center gap-4 mb-8">
|
||||
<div className="relative w-full md:w-96">
|
||||
<div className="absolute inset-y-0 left-4 flex items-center pointer-events-none"><Search size={18} className="text-[#86868B]" /></div>
|
||||
<input type="text" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} placeholder="Search by SKU, name or spec..." className="w-full bg-white dark:bg-[#111] border border-black/10 dark:border-white/10 rounded-full pl-12 pr-10 py-3.5 text-sm text-[#1D1D1F] dark:text-white outline-none focus:border-[#0066CC] dark:focus:border-amber-500 transition-colors shadow-sm" />
|
||||
<input type="text" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} placeholder={t("searchPlaceholder")} className="w-full bg-white dark:bg-[#111] border border-black/10 dark:border-white/10 rounded-full pl-12 pr-10 py-3.5 text-sm text-[#1D1D1F] dark:text-white outline-none focus:border-[#0066CC] dark:focus:border-amber-500 transition-colors shadow-sm" />
|
||||
{searchTerm && <button onClick={() => setSearchTerm("")} className="absolute inset-y-0 right-4 flex items-center text-[#86868B] hover:text-[#1D1D1F] dark:hover:text-white transition-colors"><X size={16} /></button>}
|
||||
</div>
|
||||
<div className="text-sm text-[#86868B] font-medium">{totalItems} {totalItems === 1 ? "component found" : "components found"}</div>
|
||||
<div className="text-sm text-[#86868B] font-medium">{totalItems} {totalItems === 1 ? t("componentFound") : t("componentsFound")}</div>
|
||||
</div>
|
||||
|
||||
{initialParts.length === 0 ? (
|
||||
<div className="py-20 flex flex-col items-center justify-center text-center border border-dashed border-black/10 dark:border-white/10 rounded-[2rem] bg-white/30 dark:bg-[#111]/30">
|
||||
<Wrench size={48} className="text-[#86868B]/30 mb-4" />
|
||||
<h3 className="text-lg font-medium text-[#1D1D1F] dark:text-white mb-2">No components found</h3>
|
||||
<button onClick={() => setSearchTerm("")} className="mt-4 text-sm text-[#0066CC] dark:text-amber-500 font-medium hover:underline">Clear search</button>
|
||||
<h3 className="text-lg font-medium text-[#1D1D1F] dark:text-white mb-2">{t("noComponents")}</h3>
|
||||
<button onClick={() => setSearchTerm("")} className="mt-4 text-sm text-[#0066CC] dark:text-amber-500 font-medium hover:underline">{t("clearSearch")}</button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
||||
@@ -137,7 +136,7 @@ export default function ComponentGrid({ initialParts, locale, query, currentPage
|
||||
{totalPages > 1 && (
|
||||
<div className="flex items-center justify-center gap-4 mt-12">
|
||||
<button onClick={() => handlePageChange(currentPage - 1)} disabled={currentPage === 1} className="p-3 rounded-full bg-white dark:bg-[#111] border border-black/10 dark:border-white/10 text-[#1D1D1F] dark:text-white disabled:opacity-30 disabled:cursor-not-allowed hover:bg-black/5 dark:hover:bg-white/5 transition-colors"><ChevronLeft size={20} /></button>
|
||||
<span className="text-sm font-medium text-[#86868B]">Page <strong className="text-[#1D1D1F] dark:text-white">{currentPage}</strong> of {totalPages}</span>
|
||||
<span className="text-sm font-medium text-[#86868B]">{t("page")} <strong className="text-[#1D1D1F] dark:text-white">{currentPage}</strong> {t("of")} {totalPages}</span>
|
||||
<button onClick={() => handlePageChange(currentPage + 1)} disabled={currentPage === totalPages} className="p-3 rounded-full bg-white dark:bg-[#111] border border-black/10 dark:border-white/10 text-[#1D1D1F] dark:text-white disabled:opacity-30 disabled:cursor-not-allowed hover:bg-black/5 dark:hover:bg-white/5 transition-colors"><ChevronRight size={20} /></button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -97,7 +97,7 @@ export default function PartDetailsModal({ part, isOpen, onClose }: PartDetailsM
|
||||
) : (
|
||||
<div className="flex flex-col items-center text-[#86868B]/40">
|
||||
<Wrench size={64} className="mb-4" />
|
||||
<p className="text-sm font-medium uppercase tracking-widest">No Media Available</p>
|
||||
<p className="text-sm font-medium uppercase tracking-widest">{t("noMedia")}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -140,7 +140,7 @@ export default function PartDetailsModal({ part, isOpen, onClose }: PartDetailsM
|
||||
</h2>
|
||||
<div className="flex items-end justify-between">
|
||||
<div>
|
||||
<p className="text-[10px] uppercase tracking-widest text-[#86868B] font-semibold mb-1">Unit Price</p>
|
||||
<p className="text-[10px] uppercase tracking-widest text-[#86868B] font-semibold mb-1">{t("unitPrice")}</p>
|
||||
{part.showPrice && part.price ? (
|
||||
<p className="text-3xl font-mono font-medium text-[#1D1D1F] dark:text-white">€{part.price.toFixed(2)}</p>
|
||||
) : (
|
||||
@@ -157,10 +157,9 @@ export default function PartDetailsModal({ part, isOpen, onClose }: PartDetailsM
|
||||
{part.description && part.description !== "Draft description..." && (
|
||||
<div>
|
||||
<h3 className="text-xs uppercase tracking-widest text-[#86868B] font-semibold mb-4 flex items-center gap-2">
|
||||
<Info size={14} /> Product Overview
|
||||
<Info size={14} /> {t("productOverview")}
|
||||
</h3>
|
||||
<div className="max-w-none">
|
||||
{/* 🔥 APLICAMOS TU PARSER AQUÍ 🔥 */}
|
||||
{renderMarkdown(part.description)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -170,7 +169,7 @@ export default function PartDetailsModal({ part, isOpen, onClose }: PartDetailsM
|
||||
{specs.length > 0 && (
|
||||
<div>
|
||||
<h3 className="text-xs uppercase tracking-widest text-[#86868B] font-semibold mb-4 flex items-center gap-2">
|
||||
<Tag size={14} /> Technical Specifications
|
||||
<Tag size={14} /> {t("techSpecs")}
|
||||
</h3>
|
||||
<div className="bg-white dark:bg-black/40 rounded-2xl overflow-hidden border border-black/5 dark:border-white/5 shadow-sm">
|
||||
{specs.map((spec, idx) => (
|
||||
@@ -190,7 +189,7 @@ export default function PartDetailsModal({ part, isOpen, onClose }: PartDetailsM
|
||||
onClick={handleAddToCart}
|
||||
className="w-full bg-[#1D1D1F] dark:bg-amber-500 text-white dark:text-black py-4 rounded-xl font-semibold flex items-center justify-center gap-2 transition-transform active:scale-[0.98] hover:shadow-lg dark:hover:shadow-[0_0_20px_rgba(245,158,11,0.3)]"
|
||||
>
|
||||
<ShoppingBag size={18} /> Add to Operations Cart
|
||||
<ShoppingBag size={18} /> {t("addToCart")}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user