fixed some errors
This commit is contained in:
@@ -121,20 +121,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
[data-sonner-toast] [data-description] {
|
||||
color: #000 !important;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Animasyonları "utilities" katmanına ekliyoruz ki Tailwind sınıfları gibi davranabilsinler */
|
||||
@layer utilities {
|
||||
/* Özel Renk Sınıfları (CSS değişkenlerini kullanmak için) */
|
||||
.text-fg { color: var(--fg); }
|
||||
.bg-bg { background-color: var(--bg); }
|
||||
.stroke-primary { stroke: #005bff; }
|
||||
.text-fg {
|
||||
color: var(--fg);
|
||||
}
|
||||
.bg-bg {
|
||||
background-color: var(--bg);
|
||||
}
|
||||
.stroke-primary {
|
||||
stroke: #005bff;
|
||||
}
|
||||
|
||||
/* Dark mode track rengi için özel sınıf */
|
||||
.stroke-track {
|
||||
stroke: hsla(var(--hue), 10%, 10%, 0.1);
|
||||
transition: stroke var(--trans-dur);
|
||||
@@ -145,11 +147,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Animasyon Sınıfları */
|
||||
.animate-msg { animation: msg 0.3s 13.7s linear forwards; }
|
||||
.animate-msgLast { animation: msg 0.3s 14s linear reverse forwards; }
|
||||
.animate-cartLines { animation: cartLines 2s ease-in-out infinite; }
|
||||
.animate-cartTop { animation: cartTop 2s ease-in-out infinite; }
|
||||
.animate-msg {
|
||||
animation: msg 0.3s 13.7s linear forwards;
|
||||
}
|
||||
.animate-msgLast {
|
||||
animation: msg 0.3s 14s linear reverse forwards;
|
||||
}
|
||||
.animate-cartLines {
|
||||
animation: cartLines 2s ease-in-out infinite;
|
||||
}
|
||||
.animate-cartTop {
|
||||
animation: cartTop 2s ease-in-out infinite;
|
||||
}
|
||||
.animate-cartWheel1 {
|
||||
animation: cartWheel1 2s ease-in-out infinite;
|
||||
transform: rotate(-0.25turn);
|
||||
@@ -160,33 +169,68 @@
|
||||
transform: rotate(0.25turn);
|
||||
transform-origin: 102px 111px;
|
||||
}
|
||||
.animate-cartWheelStroke { animation: cartWheelStroke 2s ease-in-out infinite; }
|
||||
.animate-cartWheelStroke {
|
||||
animation: cartWheelStroke 2s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyframes Tanımları */
|
||||
@keyframes msg {
|
||||
from { opacity: 1; visibility: visible; }
|
||||
99.9% { opacity: 0; visibility: visible; }
|
||||
to { opacity: 0; visibility: hidden; }
|
||||
from {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
99.9% {
|
||||
opacity: 0;
|
||||
visibility: visible;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
@keyframes cartLines {
|
||||
from, to { opacity: 0; }
|
||||
8%, 92% { opacity: 1; }
|
||||
from,
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
8%,
|
||||
92% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes cartTop {
|
||||
from { stroke-dashoffset: -338; }
|
||||
50% { stroke-dashoffset: 0; }
|
||||
to { stroke-dashoffset: 338; }
|
||||
from {
|
||||
stroke-dashoffset: -338;
|
||||
}
|
||||
50% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
to {
|
||||
stroke-dashoffset: 338;
|
||||
}
|
||||
}
|
||||
@keyframes cartWheel1 {
|
||||
from { transform: rotate(-0.25turn); }
|
||||
to { transform: rotate(2.75turn); }
|
||||
from {
|
||||
transform: rotate(-0.25turn);
|
||||
}
|
||||
to {
|
||||
transform: rotate(2.75turn);
|
||||
}
|
||||
}
|
||||
@keyframes cartWheel2 {
|
||||
from { transform: rotate(0.25turn); }
|
||||
to { transform: rotate(3.25turn); }
|
||||
from {
|
||||
transform: rotate(0.25turn);
|
||||
}
|
||||
to {
|
||||
transform: rotate(3.25turn);
|
||||
}
|
||||
}
|
||||
@keyframes cartWheelStroke {
|
||||
from, to { stroke-dashoffset: 81.68; }
|
||||
50% { stroke-dashoffset: 40.84; }
|
||||
from,
|
||||
to {
|
||||
stroke-dashoffset: 81.68;
|
||||
}
|
||||
50% {
|
||||
stroke-dashoffset: 40.84;
|
||||
}
|
||||
}
|
||||
@@ -54,10 +54,7 @@ interface FormErrors {
|
||||
file?: string;
|
||||
}
|
||||
|
||||
export default function OpenStorePage({
|
||||
locale = "ru",
|
||||
translations,
|
||||
}: OpenStorePageProps) {
|
||||
export default function OpenStorePage({}: OpenStorePageProps) {
|
||||
const [formData, setFormData] = useState<FormData>({
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
@@ -76,21 +73,21 @@ export default function OpenStorePage({
|
||||
const newErrors: FormErrors = {};
|
||||
|
||||
if (!formData.firstName.trim()) {
|
||||
newErrors.firstName = t("firstNameRequired");
|
||||
newErrors.firstName = t("requiredField");
|
||||
}
|
||||
|
||||
if (!formData.lastName.trim()) {
|
||||
newErrors.lastName = t("lastNameRequired");
|
||||
newErrors.lastName = t("requiredField");
|
||||
}
|
||||
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(formData.email)) {
|
||||
newErrors.email = t("emailInvalid");
|
||||
newErrors.email = t("requiredField");
|
||||
}
|
||||
|
||||
const phoneRegex = /^\+?[0-9]{6,15}$/;
|
||||
if (!phoneRegex.test(formData.phone)) {
|
||||
newErrors.phone = t("phoneInvalid");
|
||||
newErrors.phone = t("requiredField");
|
||||
}
|
||||
|
||||
if (!formData.file) {
|
||||
|
||||
@@ -46,11 +46,10 @@ export default function ErrorPage() {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white flex flex-col items-center justify-start overflow-hidden font-['Encode_Sans_Semi_Condensed',_sans-serif]">
|
||||
{/* CSS Animasyonlarını buraya gömüyoruz */}
|
||||
<style dangerouslySetInnerHTML={{ __html: fontImport }} />
|
||||
|
||||
<h1
|
||||
className={`text-[10rem] leading-[10rem] font-extralight text-black transition-all duration-500 ease-linear
|
||||
className={`text-[10rem] leading-40 font-extralight text-black transition-all duration-500 ease-linear
|
||||
${isLoading ? "mt-0 opacity-0" : "mt-[100px] opacity-100"}`}
|
||||
>
|
||||
500
|
||||
@@ -110,7 +109,6 @@ export default function ErrorPage() {
|
||||
);
|
||||
}
|
||||
|
||||
// Dişli çubukları için yardımcı bileşen
|
||||
function GearBars() {
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import {
|
||||
CircleCheckIcon,
|
||||
@@ -6,12 +6,12 @@ import {
|
||||
Loader2Icon,
|
||||
OctagonXIcon,
|
||||
TriangleAlertIcon,
|
||||
} from "lucide-react"
|
||||
import { useTheme } from "next-themes"
|
||||
import { Toaster as Sonner, type ToasterProps } from "sonner"
|
||||
} from "lucide-react";
|
||||
import { useTheme } from "next-themes";
|
||||
import { Toaster as Sonner, type ToasterProps } from "sonner";
|
||||
|
||||
const Toaster = ({ ...props }: ToasterProps) => {
|
||||
const { theme = "system" } = useTheme()
|
||||
const { theme = "system" } = useTheme();
|
||||
|
||||
return (
|
||||
<Sonner
|
||||
@@ -24,17 +24,24 @@ const Toaster = ({ ...props }: ToasterProps) => {
|
||||
error: <OctagonXIcon className="size-4" />,
|
||||
loading: <Loader2Icon className="size-4 animate-spin" />,
|
||||
}}
|
||||
toastOptions={{
|
||||
classNames: {
|
||||
description: "text-foreground opacity-90",
|
||||
title: "font-bold",
|
||||
},
|
||||
}}
|
||||
style={
|
||||
{
|
||||
"--normal-bg": "var(--popover)",
|
||||
"--normal-text": "var(--popover-foreground)",
|
||||
"--normal-border": "var(--border)",
|
||||
"--border-radius": "var(--radius)",
|
||||
"--description-color": "var(--popover-foreground)",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export { Toaster }
|
||||
export { Toaster };
|
||||
|
||||
@@ -155,7 +155,7 @@ export default function OrderSummary({
|
||||
}`}
|
||||
/>
|
||||
{showValidation && name.trim() === "" && (
|
||||
<p className="text-xs text-red-500 mt-1">Bu alan zorunludur</p>
|
||||
<p className="text-xs text-red-500 mt-1">{t("requiredField")}</p>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
@@ -172,7 +172,7 @@ export default function OrderSummary({
|
||||
}`}
|
||||
/>
|
||||
{showValidation && lastName.trim() === "" && (
|
||||
<p className="text-xs text-red-500 mt-1">Bu alan zorunludur</p>
|
||||
<p className="text-xs text-red-500 mt-1">{t("requiredField")}</p>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
@@ -190,7 +190,7 @@ export default function OrderSummary({
|
||||
/>
|
||||
{showValidation && !isPhoneValid && (
|
||||
<p className="text-xs text-red-500 mt-1">
|
||||
Telefon 8 rakamdan oluşmalıdır
|
||||
{t("requiredField")}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
@@ -226,7 +226,7 @@ export default function OrderSummary({
|
||||
))}
|
||||
</div>
|
||||
{showValidation && !paymentType && (
|
||||
<p className="text-xs text-red-500 mt-1">Ödeme türü seçiniz</p>
|
||||
<p className="text-xs text-red-500 mt-1">{t("requiredField")}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -264,7 +264,7 @@ export default function OrderSummary({
|
||||
))}
|
||||
</RadioGroup>
|
||||
{showValidation && !selectedRegion && (
|
||||
<p className="text-xs text-red-500 mt-1">Bölge seçiniz</p>
|
||||
<p className="text-xs text-red-500 mt-1">{t("requiredField")}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -294,7 +294,7 @@ export default function OrderSummary({
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{showValidation && !selectedProvince && (
|
||||
<p className="text-xs text-red-500 mt-1">Adres seçiniz</p>
|
||||
<p className="text-xs text-red-500 mt-1">{t("requiredField")}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -382,7 +382,7 @@ export default function ProductCard({
|
||||
) : (
|
||||
<>
|
||||
<ShoppingCart className="h-4 w-4" />
|
||||
{t("checkout")}
|
||||
{t("add_to_cart")}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
@@ -111,7 +111,7 @@ export function ProductInfoCard({
|
||||
</Card>
|
||||
|
||||
{description && (
|
||||
<Card className="p-4 rounded-xl border-gray-200">
|
||||
<Card className="p-4 rounded-xl border-gray-200 gap-2">
|
||||
<h3 className="text-xl font-semibold mb-3">
|
||||
{t("product_description")}
|
||||
</h3>
|
||||
|
||||
@@ -119,6 +119,24 @@ export default function ProductPageContent({ slug }: ProductDetailProps) {
|
||||
[product]
|
||||
);
|
||||
|
||||
const transformedRelatedProducts = useMemo(() => {
|
||||
if (!relatedProducts) return [];
|
||||
return relatedProducts.map((p) => ({
|
||||
id: p.id,
|
||||
slug: p.slug,
|
||||
name: p.name,
|
||||
price_amount: p.price_amount,
|
||||
old_price_amount: p.old_price_amount ?? undefined,
|
||||
struct_price_text: `${p.price_amount} TMT`,
|
||||
discount: null,
|
||||
discount_text: null,
|
||||
stock: p.stock,
|
||||
media: p.media,
|
||||
labels: [],
|
||||
price_color: undefined,
|
||||
}));
|
||||
}, [relatedProducts]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!product?.id || isInitialized) return;
|
||||
|
||||
@@ -246,7 +264,7 @@ export default function ProductPageContent({ slug }: ProductDetailProps) {
|
||||
}
|
||||
} catch (error) {
|
||||
setLocalQuantity(cartItem?.product_quantity || 1);
|
||||
toast.error("Failed to update quantity", {
|
||||
toast.error(t("failed_to_update_quantity"), {
|
||||
description: "Please try again",
|
||||
});
|
||||
|
||||
@@ -438,10 +456,10 @@ export default function ProductPageContent({ slug }: ProductDetailProps) {
|
||||
/>
|
||||
|
||||
<ProductInfoCard
|
||||
brandName={product.brand?.name}
|
||||
brandName={product.brand?.name ?? undefined}
|
||||
stock={product.stock}
|
||||
barcode={product.barcode}
|
||||
colour={product.colour}
|
||||
colour={product.colour ?? undefined}
|
||||
properties={product.properties}
|
||||
description={product.description}
|
||||
averageRating={averageRating}
|
||||
@@ -451,7 +469,7 @@ export default function ProductPageContent({ slug }: ProductDetailProps) {
|
||||
|
||||
<ProductPurchaseCard
|
||||
price={product.price_amount}
|
||||
oldPrice={product.old_price_amount}
|
||||
oldPrice={product.old_price_amount ?? undefined}
|
||||
isInCart={isInCart}
|
||||
localQuantity={localQuantity}
|
||||
availableStock={availableStock}
|
||||
@@ -475,7 +493,7 @@ export default function ProductPageContent({ slug }: ProductDetailProps) {
|
||||
onWriteReview={() => setShowReviewModal(true)}
|
||||
/>
|
||||
|
||||
<RelatedProductsSection products={relatedProducts || []} />
|
||||
<RelatedProductsSection products={transformedRelatedProducts} />
|
||||
</div>
|
||||
|
||||
<StockLimitModal
|
||||
|
||||
@@ -45,9 +45,7 @@ export function ProductPurchaseCard({
|
||||
<div className="flex justify-between items-start mb-6">
|
||||
<span className="text-lg text-gray-500">{t("price")}:</span>
|
||||
<div className="flex flex-col items-end">
|
||||
<span className="text-3xl font-bold text-primary">
|
||||
{price} TMT
|
||||
</span>
|
||||
<span className="text-3xl font-bold text-primary">{price} TMT</span>
|
||||
{oldPrice && parseFloat(oldPrice) > 0 && (
|
||||
<span className="text-lg text-gray-400 line-through">
|
||||
{oldPrice} TMT
|
||||
@@ -102,6 +100,7 @@ export function ProductPurchaseCard({
|
||||
<Plus className="h-5 w-5" />
|
||||
</Button>
|
||||
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
@@ -123,17 +122,15 @@ export function ProductPurchaseCard({
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
size="lg"
|
||||
onClick={onAddToCart}
|
||||
disabled={isSyncing || productStock === 0}
|
||||
className="w-full rounded-lg text-lg font-bold bg-[#005bff] hover:bg-[#0041c4] cursor-pointer"
|
||||
className="flex-1 rounded-lg text-lg font-bold bg-[#005bff] hover:bg-[#0041c4] cursor-pointer"
|
||||
>
|
||||
{isSyncing ? (
|
||||
<>
|
||||
|
||||
{t("adding")}
|
||||
</>
|
||||
<>{t("adding")}</>
|
||||
) : (
|
||||
<>
|
||||
<ShoppingCart className="mr-2 h-5 w-5" />
|
||||
@@ -141,6 +138,27 @@ export function ProductPurchaseCard({
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={onToggleFavorite}
|
||||
className={`rounded-lg h-12 w-12 transition-all border cursor-pointer ${
|
||||
isFavorite
|
||||
? "bg-[#F0F8FF] border-blue-300 hover:bg-blue-100"
|
||||
: "hover:bg-gray-50"
|
||||
}`}
|
||||
>
|
||||
<Heart
|
||||
className={`h-6! w-6! transition-all ${
|
||||
isFavorite
|
||||
? "fill-[#005bff] text-[#005bff]"
|
||||
: "text-[#005bff]"
|
||||
}`}
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
@@ -158,7 +176,11 @@ export function ProductPurchaseCard({
|
||||
<h4 className="text-lg font-bold">{channelName}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<Button variant="outline" size="lg" className="w-full cursor-pointer rounded-lg">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
className="w-full cursor-pointer rounded-lg"
|
||||
>
|
||||
{t("write_to_store")}
|
||||
</Button>
|
||||
</Card>
|
||||
|
||||
@@ -78,7 +78,7 @@ export default function ClientProfilePage(props: ProfilePageProps) {
|
||||
|
||||
const handleSave = useCallback(async () => {
|
||||
if (!formData.name.trim()) {
|
||||
toast.error(t("name_required") || "Name is required");
|
||||
toast.error(t("requiredField") || "Name is required");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,9 +33,6 @@
|
||||
"address_search": "Поиск адреса",
|
||||
"address": "Адрес",
|
||||
"first_name": "Имя",
|
||||
"building": "Дом",
|
||||
"floor": "Этаж",
|
||||
"apartment": "Кв",
|
||||
"save": "Сохранить",
|
||||
"enter_phone": "Введите свой номер телефона",
|
||||
"code_will_be_sent": "Мы вышлем вам код",
|
||||
@@ -102,6 +99,7 @@
|
||||
"empty_favorites": "У вас пока нет избранных товаров",
|
||||
"removed_from_favorites": "Товар удален из избранного",
|
||||
"added_to_cart": "Товар добавлен в корзину",
|
||||
"failed_to_update_quantity": "Количество не удалось обновить",
|
||||
"removed_from_cart": "Товар удален из корзины",
|
||||
"error": "Произошла ошибка",
|
||||
"out_of_stock": "Нет в наличии",
|
||||
@@ -190,7 +188,9 @@
|
||||
"title": "Открыть магазин",
|
||||
"enter_email": "Введите email",
|
||||
"uploadPatent": "Загрузить патент",
|
||||
"outOfStock": "Нет в наличии"
|
||||
"outOfStock": "Нет в наличии",
|
||||
"requiredField": "Обязательное поле",
|
||||
"fileRequired": "Файл загрузить"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,9 +33,6 @@
|
||||
"address_search": "Adres gözleg",
|
||||
"address": "Adres",
|
||||
"first_name": "Ady",
|
||||
"building": "Jaý",
|
||||
"floor": "Gat",
|
||||
"apartment": "Otag",
|
||||
"save": "Ýatda sakla",
|
||||
"enter_phone": "Telefon belgisini giriziň",
|
||||
"code_will_be_sent": "Biz size kod ugradarys",
|
||||
@@ -78,7 +75,7 @@
|
||||
"no": "Ýok",
|
||||
"yes": "Hawa",
|
||||
"cart_empty": "Siziň söwda sebediňiz boş",
|
||||
"add_to_cart": "Söwda sebedine üstünlikli goşuldy",
|
||||
"add_to_cart": "Sebede goş",
|
||||
|
||||
"go_to_cart": "Sebede geçmek",
|
||||
"products": "Azyk harytlary",
|
||||
@@ -103,6 +100,7 @@
|
||||
"empty_favorites": "Siziň saýlanan harytlaryňyz ýok",
|
||||
"removed_from_favorites": "Haryt saýlanlardan aýryldy",
|
||||
"added_to_cart": "Haryt sebede goşuldy",
|
||||
"failed_to_update_quantity": "Mukdar täzelenip bolmady",
|
||||
"removed_from_cart": "Haryt sebetden aýryldy",
|
||||
"error": "Ýalňyşlyk ýüze çykdy",
|
||||
"out_of_stock": "Haryt ýok",
|
||||
@@ -191,5 +189,7 @@
|
||||
"title": "Magazin aç",
|
||||
"enter_email": "Poçtaňyzy ýazyň",
|
||||
"uploadPatent": "Patent goş",
|
||||
"outOfStock": "Ammarda ýok"
|
||||
"outOfStock": "Ammarda ýok",
|
||||
"requiredField": "Zerur maglumat",
|
||||
"fileRequired": "Fayl goş"
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ class APIClient {
|
||||
|
||||
constructor() {
|
||||
this.baseUrl = process.env.NEXT_PUBLIC_API_URL || "https://api.example.com";
|
||||
console.log("API URL:", this.baseUrl);
|
||||
|
||||
this.client = axios.create({
|
||||
baseURL: `${this.baseUrl}/api/v1`,
|
||||
@@ -42,7 +43,7 @@ class APIClient {
|
||||
}
|
||||
|
||||
// Add language parameter
|
||||
let lang = "tk";
|
||||
let lang = "tm";
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
if ((window as any).i18n?.language) {
|
||||
|
||||
@@ -5,7 +5,7 @@ const withNextIntl = createNextIntlPlugin("./i18n/i18n.ts")
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
ignoreBuildErrors: false,
|
||||
},
|
||||
images: {
|
||||
unoptimized: true,
|
||||
|
||||
2243
package-lock.json
generated
2243
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user