Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f737566c2 | |||
| 458ac401fd | |||
| 9c68f66c75 | |||
| 6480b018fd | |||
| 2150c392b3 | |||
| a4ecac4044 | |||
| d18999f563 | |||
| a0900563ff | |||
| d72637aa74 | |||
| f6e47dcb15 | |||
| ae5f1922a4 | |||
| b08690bb9a | |||
| 32e0ca77c5 | |||
| 29da3bb51c | |||
| 5b7bdf372c |
82
src/app/about/page.tsx
Normal file
82
src/app/about/page.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import TextAbout from "@/components/sections/about/TextAbout";
|
||||
import FooterBaseCard from "@/components/sections/footer/FooterBaseCard";
|
||||
|
||||
export default function AboutPage() {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-shift"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="mediumSmall"
|
||||
sizing="mediumLarge"
|
||||
background="circleGradient"
|
||||
cardStyle="subtle-shadow"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
brandName="Fatinur Flowers"
|
||||
navItems={[
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Catalog", id: "/catalog" },
|
||||
{ name: "About", id: "/about" },
|
||||
{ name: "Delivery", id: "/delivery" },
|
||||
{ name: "Contact", id: "/contact" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="about" data-section="about" className="pt-20">
|
||||
<TextAbout
|
||||
tag="💝 Our Story"
|
||||
title="Fatinur Flowers - Expressing Love and Beauty Through Flowers"
|
||||
useInvertedBackground={false}
|
||||
buttons={[{ text: "Contact Us", href: "/contact" }]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Fatinur Flowers"
|
||||
columns={[
|
||||
{
|
||||
title: "Products", items: [
|
||||
{ label: "Flower Catalog", href: "/catalog" },
|
||||
{ label: "Categories", href: "/catalog" },
|
||||
{ label: "Popular Bouquets", href: "/catalog" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About Us", href: "/about" },
|
||||
{ label: "Delivery Info", href: "/delivery" },
|
||||
{ label: "Contact", href: "/contact" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Connect", items: [
|
||||
{ label: "Telegram", href: "https://t.me/fatinur_flowers" },
|
||||
{ label: "Instagram", href: "https://instagram.com/fatinur_flowers" },
|
||||
{ label: "WhatsApp", href: "https://wa.me/998901234567" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Legal", items: [
|
||||
{ label: "Privacy Policy", href: "/privacy" },
|
||||
{ label: "Terms of Service", href: "/terms" },
|
||||
{ label: "Cookie Policy", href: "/cookies" },
|
||||
],
|
||||
},
|
||||
]}
|
||||
copyrightText="© 2025 Fatinur Flowers. All rights reserved."
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
633
src/app/admin/page.tsx
Normal file
633
src/app/admin/page.tsx
Normal file
@@ -0,0 +1,633 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import FooterBaseCard from "@/components/sections/footer/FooterBaseCard";
|
||||
import Input from "@/components/form/Input";
|
||||
import {
|
||||
LogOut,
|
||||
Package,
|
||||
FolderOpen,
|
||||
ShoppingCart,
|
||||
Users,
|
||||
TrendingUp,
|
||||
Upload,
|
||||
Edit,
|
||||
Trash2,
|
||||
Plus,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
|
||||
type AdminTab = "login" | "products" | "categories" | "orders" | "customers" | "analytics";
|
||||
|
||||
interface Product {
|
||||
id: string;
|
||||
name: string;
|
||||
price: number;
|
||||
category: string;
|
||||
image?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
interface Category {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface Order {
|
||||
id: string;
|
||||
customerName: string;
|
||||
status: "pending" | "processing" | "delivered" | "cancelled";
|
||||
total: number;
|
||||
date: string;
|
||||
}
|
||||
|
||||
interface Customer {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
orders: number;
|
||||
}
|
||||
|
||||
export default function AdminPanel() {
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
||||
const [currentTab, setCurrentTab] = useState<AdminTab>("login");
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
|
||||
// Products state
|
||||
const [products, setProducts] = useState<Product[]>([
|
||||
{
|
||||
id: "1", name: "Qizil Roza Buket", price: 250000,
|
||||
category: "Rozalar", description: "Premium qizil rozalar"},
|
||||
{
|
||||
id: "2", name: "Tula Aralash", price: 180000,
|
||||
category: "Tulalar", description: "Aralash rangli tulalar"},
|
||||
]);
|
||||
const [newProduct, setNewProduct] = useState<Partial<Product>>({
|
||||
name: "", price: 0,
|
||||
category: "", description: ""});
|
||||
const [editingProductId, setEditingProductId] = useState<string | null>(null);
|
||||
|
||||
// Categories state
|
||||
const [categories, setCategories] = useState<Category[]>([
|
||||
{ id: "1", name: "Rozalar" },
|
||||
{ id: "2", name: "Tulalar" },
|
||||
{ id: "3", name: "Siyavushlar" },
|
||||
]);
|
||||
const [newCategory, setNewCategory] = useState("");
|
||||
|
||||
// Orders state
|
||||
const [orders, setOrders] = useState<Order[]>([
|
||||
{
|
||||
id: "1", customerName: "Ayubjon Raximov", status: "delivered", total: 250000,
|
||||
date: "2025-01-15"},
|
||||
{
|
||||
id: "2", customerName: "Dilorom Ibragimova", status: "processing", total: 180000,
|
||||
date: "2025-01-16"},
|
||||
]);
|
||||
|
||||
// Customers state
|
||||
const [customers] = useState<Customer[]>([
|
||||
{
|
||||
id: "1", name: "Ayubjon Raximov", email: "ayubjon@example.com", phone: "+998901234567", orders: 5,
|
||||
},
|
||||
{
|
||||
id: "2", name: "Dilorom Ibragimova", email: "dilorom@example.com", phone: "+998912345678", orders: 3,
|
||||
},
|
||||
]);
|
||||
|
||||
// Analytics data
|
||||
const topSellingProducts = [
|
||||
{ name: "Qizil Roza Buket", sales: 45 },
|
||||
{ name: "Tula Aralash", sales: 32 },
|
||||
{ name: "Oyoq Buket", sales: 28 },
|
||||
{ name: "Oq Lililar", sales: 19 },
|
||||
];
|
||||
|
||||
const handleLogin = () => {
|
||||
if (email === "admin@fatinur.com" && password === "admin123") {
|
||||
setIsAuthenticated(true);
|
||||
setCurrentTab("products");
|
||||
setEmail("");
|
||||
setPassword("");
|
||||
} else {
|
||||
alert("Login yoki parol noto'g'ri");
|
||||
}
|
||||
};
|
||||
|
||||
const handleLogout = () => {
|
||||
setIsAuthenticated(false);
|
||||
setCurrentTab("login");
|
||||
};
|
||||
|
||||
const handleAddProduct = () => {
|
||||
if (newProduct.name && newProduct.price && newProduct.category) {
|
||||
if (editingProductId) {
|
||||
setProducts(
|
||||
products.map((p) =>
|
||||
p.id === editingProductId
|
||||
? { ...p, ...newProduct }
|
||||
: p
|
||||
) as Product[]
|
||||
);
|
||||
setEditingProductId(null);
|
||||
} else {
|
||||
setProducts([
|
||||
...products,
|
||||
{
|
||||
id: Date.now().toString(),
|
||||
name: newProduct.name,
|
||||
price: newProduct.price,
|
||||
category: newProduct.category,
|
||||
description: newProduct.description || ""},
|
||||
]);
|
||||
}
|
||||
setNewProduct({ name: "", price: 0, category: "", description: "" });
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteProduct = (id: string) => {
|
||||
setProducts(products.filter((p) => p.id !== id));
|
||||
};
|
||||
|
||||
const handleAddCategory = () => {
|
||||
if (newCategory.trim()) {
|
||||
setCategories([
|
||||
...categories,
|
||||
{ id: Date.now().toString(), name: newCategory },
|
||||
]);
|
||||
setNewCategory("");
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteCategory = (id: string) => {
|
||||
setCategories(categories.filter((c) => c.id !== id));
|
||||
};
|
||||
|
||||
const handleUpdateOrderStatus = (orderId: string, newStatus: Order["status"]) => {
|
||||
setOrders(
|
||||
orders.map((o) => (o.id === orderId ? { ...o, status: newStatus } : o))
|
||||
);
|
||||
};
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-shift"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="mediumSmall"
|
||||
sizing="mediumLarge"
|
||||
background="circleGradient"
|
||||
cardStyle="subtle-shadow"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
brandName="Fatinur Flowers"
|
||||
navItems={[
|
||||
{ name: "Бош сахифа", id: "/" },
|
||||
{ name: "Admin", id: "/admin" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="min-h-[calc(100vh-80px)] flex items-center justify-center bg-background p-4">
|
||||
<div className="w-full max-w-md p-8 rounded-lg bg-card border border-background-accent shadow-lg">
|
||||
<h1 className="text-3xl font-bold mb-8 text-center text-foreground">
|
||||
Admin Panel
|
||||
</h1>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-foreground mb-2">
|
||||
Email
|
||||
</label>
|
||||
<Input
|
||||
value={email}
|
||||
onChange={setEmail}
|
||||
type="email"
|
||||
placeholder="admin@fatinur.com"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-foreground mb-2">
|
||||
Parol
|
||||
</label>
|
||||
<Input
|
||||
value={password}
|
||||
onChange={setPassword}
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleLogin}
|
||||
className="w-full bg-primary-cta text-white py-2 px-4 rounded-lg hover:opacity-90 font-medium transition-opacity"
|
||||
>
|
||||
Kirish
|
||||
</button>
|
||||
<p className="text-sm text-foreground/60 text-center mt-4">
|
||||
Demo credentials: admin@fatinur.com / admin123
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Fatinur Flowers"
|
||||
columns={[
|
||||
{
|
||||
title: "Aloqa", items: [
|
||||
{ label: "Telegram", href: "https://t.me/fatinur_flowers" },
|
||||
{ label: "Instagram", href: "https://instagram.com/fatinur_flowers" },
|
||||
],
|
||||
},
|
||||
]}
|
||||
copyrightText="© 2025 Fatinur Flowers Admin"
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-shift"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="mediumSmall"
|
||||
sizing="mediumLarge"
|
||||
background="circleGradient"
|
||||
cardStyle="subtle-shadow"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
brandName="Fatinur Flowers Admin"
|
||||
navItems={[
|
||||
{ name: "Асоси", id: "/admin" },
|
||||
{ name: "Товарлар", id: "/admin#products" },
|
||||
{ name: "Категорияlar", id: "/admin#categories" },
|
||||
{ name: "Buyurtmalar", id: "/admin#orders" },
|
||||
{ name: "Чиқиш", id: "/" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="min-h-[calc(100vh-80px)] bg-background p-6">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Header */}
|
||||
<div className="flex justify-between items-center mb-8">
|
||||
<h1 className="text-4xl font-bold text-foreground">Admin Panel</h1>
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
className="flex items-center gap-2 bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition-colors"
|
||||
>
|
||||
<LogOut size={20} />
|
||||
Чиқиш
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Navigation Tabs */}
|
||||
<div className="flex gap-4 mb-8 overflow-x-auto">
|
||||
{[
|
||||
{ id: "products", label: "Товарлар", icon: Package },
|
||||
{ id: "categories", label: "Категорияlar", icon: FolderOpen },
|
||||
{ id: "orders", label: "Buyurtmalar", icon: ShoppingCart },
|
||||
{ id: "customers", label: "Мижозлар", icon: Users },
|
||||
{ id: "analytics", label: "Статистика", icon: TrendingUp },
|
||||
].map((tab) => {
|
||||
const Icon = tab.icon;
|
||||
return (
|
||||
<button
|
||||
key={tab.id}
|
||||
onClick={() => setCurrentTab(tab.id as AdminTab)}
|
||||
className={`flex items-center gap-2 px-4 py-2 rounded-lg transition-all ${
|
||||
currentTab === tab.id
|
||||
? "bg-primary-cta text-white"
|
||||
: "bg-card text-foreground hover:bg-background-accent"
|
||||
}`}
|
||||
>
|
||||
<Icon size={20} />
|
||||
{tab.label}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="bg-card rounded-lg p-6 border border-background-accent">
|
||||
{/* Products Tab */}
|
||||
{currentTab === "products" && (
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-2xl font-bold text-foreground">Махсулотларни Бошқариш</h2>
|
||||
|
||||
{/* Add Product Form */}
|
||||
<div className="bg-background rounded-lg p-4 space-y-4">
|
||||
<h3 className="text-lg font-semibold text-foreground">
|
||||
{editingProductId ? "Махсулотни Редактировать" : "Янги Махсулот Қўшиш"}
|
||||
</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<Input
|
||||
value={newProduct.name || ""}
|
||||
onChange={(val) =>
|
||||
setNewProduct({ ...newProduct, name: val })
|
||||
}
|
||||
placeholder="Махсулот номи"
|
||||
/>
|
||||
<Input
|
||||
value={newProduct.price?.toString() || ""}
|
||||
onChange={(val) =>
|
||||
setNewProduct({ ...newProduct, price: Number(val) })
|
||||
}
|
||||
type="number"
|
||||
placeholder="Нарх"
|
||||
/>
|
||||
<Input
|
||||
value={newProduct.category || ""}
|
||||
onChange={(val) =>
|
||||
setNewProduct({ ...newProduct, category: val })
|
||||
}
|
||||
placeholder="Категория"
|
||||
/>
|
||||
<Input
|
||||
value={newProduct.description || ""}
|
||||
onChange={(val) =>
|
||||
setNewProduct({ ...newProduct, description: val })
|
||||
}
|
||||
placeholder="Тавсифи"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={handleAddProduct}
|
||||
className="flex items-center gap-2 bg-primary-cta text-white px-4 py-2 rounded-lg hover:opacity-90 transition-opacity"
|
||||
>
|
||||
<Plus size={20} />
|
||||
{editingProductId ? "Янгилаш" : "Қўшиш"}
|
||||
</button>
|
||||
{editingProductId && (
|
||||
<button
|
||||
onClick={() => {
|
||||
setEditingProductId(null);
|
||||
setNewProduct({ name: "", price: 0, category: "", description: "" });
|
||||
}}
|
||||
className="flex items-center gap-2 bg-background-accent text-foreground px-4 py-2 rounded-lg hover:opacity-90 transition-opacity"
|
||||
>
|
||||
<X size={20} />
|
||||
Беккор
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Products List */}
|
||||
<div className="space-y-2">
|
||||
{products.map((product) => (
|
||||
<div
|
||||
key={product.id}
|
||||
className="flex justify-between items-center p-4 bg-background rounded-lg border border-background-accent"
|
||||
>
|
||||
<div>
|
||||
<h4 className="font-semibold text-foreground">{product.name}</h4>
|
||||
<p className="text-sm text-foreground/60">
|
||||
Категория: {product.category} | Нарх: {product.price.toLocaleString()} so'm
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={() => {
|
||||
setEditingProductId(product.id);
|
||||
setNewProduct(product);
|
||||
}}
|
||||
className="p-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors"
|
||||
>
|
||||
<Edit size={18} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleDeleteProduct(product.id)}
|
||||
className="p-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors"
|
||||
>
|
||||
<Trash2 size={18} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Categories Tab */}
|
||||
{currentTab === "categories" && (
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-2xl font-bold text-foreground">Категорияларни Бошқариш</h2>
|
||||
|
||||
{/* Add Category Form */}
|
||||
<div className="bg-background rounded-lg p-4 space-y-4">
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
value={newCategory}
|
||||
onChange={setNewCategory}
|
||||
placeholder="Янги категория номи"
|
||||
/>
|
||||
<button
|
||||
onClick={handleAddCategory}
|
||||
className="bg-primary-cta text-white px-6 py-2 rounded-lg hover:opacity-90 transition-opacity"
|
||||
>
|
||||
Қўшиш
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Categories List */}
|
||||
<div className="space-y-2">
|
||||
{categories.map((category) => (
|
||||
<div
|
||||
key={category.id}
|
||||
className="flex justify-between items-center p-4 bg-background rounded-lg border border-background-accent"
|
||||
>
|
||||
<span className="text-foreground font-medium">{category.name}</span>
|
||||
<button
|
||||
onClick={() => handleDeleteCategory(category.id)}
|
||||
className="p-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors"
|
||||
>
|
||||
<Trash2 size={18} />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Orders Tab */}
|
||||
{currentTab === "orders" && (
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-2xl font-bold text-foreground">Buyurtmаларни Бошқариш</h2>
|
||||
|
||||
{/* Orders List */}
|
||||
<div className="space-y-3">
|
||||
{orders.map((order) => (
|
||||
<div
|
||||
key={order.id}
|
||||
className="p-4 bg-background rounded-lg border border-background-accent"
|
||||
>
|
||||
<div className="flex justify-between items-center mb-3">
|
||||
<div>
|
||||
<h4 className="font-semibold text-foreground">ID: {order.id}</h4>
|
||||
<p className="text-sm text-foreground/60">{order.customerName}</p>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="font-semibold text-foreground">
|
||||
{order.total.toLocaleString()} so'm
|
||||
</p>
|
||||
<p className="text-sm text-foreground/60">{order.date}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
{[
|
||||
"pending", "processing", "delivered", "cancelled"].map((status) => (
|
||||
<button
|
||||
key={status}
|
||||
onClick={() =>
|
||||
handleUpdateOrderStatus(
|
||||
order.id,
|
||||
status as Order["status"]
|
||||
)
|
||||
}
|
||||
className={`px-3 py-1 text-sm rounded-lg transition-all ${
|
||||
order.status === status
|
||||
? "bg-primary-cta text-white"
|
||||
: "bg-background-accent text-foreground hover:opacity-75"
|
||||
}`}
|
||||
>
|
||||
{status === "pending"
|
||||
? "Kutilmoqda"
|
||||
: status === "processing"
|
||||
? "Qayta Ishlash"
|
||||
: status === "delivered"
|
||||
? "Yetkazib berish"
|
||||
: "Bekor qilish"}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Customers Tab */}
|
||||
{currentTab === "customers" && (
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-2xl font-bold text-foreground">Мижозларни Кўриш</h2>
|
||||
|
||||
{/* Customers List */}
|
||||
<div className="space-y-2">
|
||||
{customers.map((customer) => (
|
||||
<div
|
||||
key={customer.id}
|
||||
className="p-4 bg-background rounded-lg border border-background-accent"
|
||||
>
|
||||
<div className="flex justify-between items-start">
|
||||
<div>
|
||||
<h4 className="font-semibold text-foreground">{customer.name}</h4>
|
||||
<p className="text-sm text-foreground/60">{customer.email}</p>
|
||||
<p className="text-sm text-foreground/60">{customer.phone}</p>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="font-semibold text-foreground">Buyurtmalar: {customer.orders}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Analytics Tab */}
|
||||
{currentTab === "analytics" && (
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-2xl font-bold text-foreground">
|
||||
Энг Йўқори Сотувчи Гуллар
|
||||
</h2>
|
||||
|
||||
{/* Top Selling Products */}
|
||||
<div className="space-y-3">
|
||||
{topSellingProducts.map((product, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="p-4 bg-background rounded-lg border border-background-accent"
|
||||
>
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<h4 className="font-semibold text-foreground">
|
||||
{index + 1}. {product.name}
|
||||
</h4>
|
||||
<span className="text-lg font-bold text-primary-cta">
|
||||
{product.sales} сотув
|
||||
</span>
|
||||
</div>
|
||||
<div className="w-full bg-background-accent rounded-full h-2">
|
||||
<div
|
||||
className="bg-primary-cta h-2 rounded-full"
|
||||
style={{
|
||||
width: `${(
|
||||
(product.sales / topSellingProducts[0].sales) *
|
||||
100
|
||||
).toFixed(0)}%`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Summary Stats */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-6">
|
||||
<div className="p-4 bg-background rounded-lg border border-background-accent">
|
||||
<p className="text-foreground/60 text-sm">Умумий Махсулотлар</p>
|
||||
<p className="text-3xl font-bold text-foreground">{products.length}</p>
|
||||
</div>
|
||||
<div className="p-4 bg-background rounded-lg border border-background-accent">
|
||||
<p className="text-foreground/60 text-sm">Умумий Buyurtmalar</p>
|
||||
<p className="text-3xl font-bold text-foreground">{orders.length}</p>
|
||||
</div>
|
||||
<div className="p-4 bg-background rounded-lg border border-background-accent">
|
||||
<p className="text-foreground/60 text-sm">Умумий Мижозлар</p>
|
||||
<p className="text-3xl font-bold text-foreground">{customers.length}</p>
|
||||
</div>
|
||||
<div className="p-4 bg-background rounded-lg border border-background-accent">
|
||||
<p className="text-foreground/60 text-sm">Кўп Сотувчи Категория</p>
|
||||
<p className="text-3xl font-bold text-foreground">Розалар</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Fatinur Flowers Admin"
|
||||
columns={[
|
||||
{
|
||||
title: "Aloqa", items: [
|
||||
{ label: "Telegram", href: "https://t.me/fatinur_flowers" },
|
||||
{ label: "Instagram", href: "https://instagram.com/fatinur_flowers" },
|
||||
],
|
||||
},
|
||||
]}
|
||||
copyrightText="© 2025 Fatinur Flowers Admin Panel"
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
136
src/app/api/orders/route.ts
Normal file
136
src/app/api/orders/route.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
interface OrderData {
|
||||
fullName: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
address: string;
|
||||
city: string;
|
||||
postalCode: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
// Mock in-memory database for demonstration
|
||||
const orders: OrderData[] = [];
|
||||
|
||||
// Telegram Bot configuration
|
||||
const TELEGRAM_BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN || "";
|
||||
const TELEGRAM_CHAT_ID = process.env.TELEGRAM_CHAT_ID || "";
|
||||
|
||||
async function sendTelegramNotification(order: OrderData) {
|
||||
if (!TELEGRAM_BOT_TOKEN || !TELEGRAM_CHAT_ID) {
|
||||
console.warn(
|
||||
"Telegram credentials not configured. Skipping notification."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const message = `
|
||||
🌸 *YANGI BUYURTMA* 🌸
|
||||
|
||||
👤 *Ism:* ${order.fullName}
|
||||
📧 *Email:* ${order.email}
|
||||
📞 *Telefon:* ${order.phone}
|
||||
|
||||
📍 *Manzil:* ${order.address}, ${order.city}
|
||||
📮 *Postal kod:* ${order.postalCode || "Berilmagan"}
|
||||
|
||||
💬 *Xabar:* ${order.message || "Xabar berilmagan"}
|
||||
|
||||
⏰ *Vaqti:* ${new Date().toLocaleString("uz-UZ")}
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`,
|
||||
{
|
||||
method: "POST", headers: {
|
||||
"Content-Type": "application/json"},
|
||||
body: JSON.stringify({
|
||||
chat_id: TELEGRAM_CHAT_ID,
|
||||
text: message,
|
||||
parse_mode: "Markdown"}),
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Telegram API error: ${response.statusText}`);
|
||||
}
|
||||
|
||||
console.log("Telegram notification sent successfully");
|
||||
} catch (error) {
|
||||
console.error("Failed to send Telegram notification:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body: OrderData = await request.json();
|
||||
|
||||
// Validate required fields
|
||||
if (
|
||||
!body.fullName ||
|
||||
!body.email ||
|
||||
!body.phone ||
|
||||
!body.address ||
|
||||
!body.city
|
||||
) {
|
||||
return NextResponse.json(
|
||||
{ error: "Missing required fields" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Add timestamp and ID
|
||||
const orderWithMetadata = {
|
||||
...body,
|
||||
id: Date.now().toString(),
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
// Save to mock database
|
||||
orders.push(body);
|
||||
console.log("Order saved to database:", orderWithMetadata);
|
||||
|
||||
// Send Telegram notification
|
||||
await sendTelegramNotification(body);
|
||||
|
||||
// Return success response
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
message: "Buyurtma muvaffaqiyatli qabul qilindi", orderId: orderWithMetadata.id,
|
||||
},
|
||||
{ status: 201 }
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Error processing order:", error);
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: "Buyurtmani qayta ishlashda xatolik yuz berdi"},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
return NextResponse.json(
|
||||
{
|
||||
orders,
|
||||
total: orders.length,
|
||||
},
|
||||
{ status: 200 }
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Error fetching orders:", error);
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: "Buyurtmalarni olishda xatolik yuz berdi" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
325
src/app/catalog/[id]/page.tsx
Normal file
325
src/app/catalog/[id]/page.tsx
Normal file
@@ -0,0 +1,325 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import FooterBaseCard from "@/components/sections/footer/FooterBaseCard";
|
||||
import { Heart, Share2, Truck, Shield, RotateCcw } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
const products: { [key: string]: any } = {
|
||||
"1": {
|
||||
id: "1", name: "Qizil Roza Buket", price: "250,000 so'm", description: "Eng sifatli qizil rozalardan tayyorlangan, sevgi va ishtiyoqni ifodalovchi luxurious buket.", images: [
|
||||
"http://img.b2bpic.net/free-photo/beautifully-wrapped-gift-bouquet-roses_169016-8520.jpg?_wi=2", "http://img.b2bpic.net/free-photo/side-view-yellow-red-tulip-flower-grey_140725-12248.jpg?_wi=2"],
|
||||
category: "Rozalar", rating: 4.8,
|
||||
reviews: 45,
|
||||
details: [
|
||||
"20+ qizil roza", "Yangi gullar", "Professional dizayn", "Zita oramiga o'ralgan"],
|
||||
},
|
||||
"2": {
|
||||
id: "2", name: "Tula Aralash", price: "180,000 so'm", description: "Turli rangdagi tulalardan tayyorlangan, ko'pikka va optimizmni ifodalovchi buket.", images: [
|
||||
"http://img.b2bpic.net/free-photo/side-view-yellow-red-tulip-flower-grey_140725-12248.jpg?_wi=2", "http://img.b2bpic.net/free-photo/beautifully-wrapped-gift-bouquet-roses_169016-8520.jpg?_wi=2"],
|
||||
category: "Tulalar", rating: 4.6,
|
||||
reviews: 32,
|
||||
details: [
|
||||
"15+ turli rang tula", "Bahor hissiyoti", "Chiroyli dizayn", "Sifatli oramiga"],
|
||||
},
|
||||
"3": {
|
||||
id: "3", name: "Oyoq Buket", price: "220,000 so'm", description: "Jonli sariq oyoqlardan tayyorlangan, xursandlik va farovonlikni ifodalovchi buket.", images: [
|
||||
"http://img.b2bpic.net/free-photo/top-view-sunflowers-frame-with-copy-space_23-2150250788.jpg?_wi=2", "http://img.b2bpic.net/free-photo/side-view-bouquet-peach-cream-color-roses-with-asparagus-grey-wooden-background_141793-7974.jpg?_wi=2"],
|
||||
category: "Oyoqlar", rating: 4.9,
|
||||
reviews: 58,
|
||||
details: [
|
||||
"12+ sariq oyoq", "Yangi yetkazildi", "Jonli rang", "Premium dizayn"],
|
||||
},
|
||||
"4": {
|
||||
id: "4", name: "Oq Lililar", price: "280,000 so'm", description: "Nozik oq lililardan tayyorlangan, murassa va qilburchi hissiyotini ifodalovchi buket.", images: [
|
||||
"http://img.b2bpic.net/free-photo/side-view-bouquet-peach-cream-color-roses-with-asparagus-grey-wooden-background_141793-7974.jpg?_wi=2", "http://img.b2bpic.net/free-photo/beautifully-wrapped-gift-bouquet-roses_169016-8520.jpg?_wi=2"],
|
||||
category: "Lililar", rating: 4.7,
|
||||
reviews: 41,
|
||||
details: [
|
||||
"8+ oq lilia", "Aromatic xush hid", "Nozik shakllanish", "Luxury oramiga"],
|
||||
},
|
||||
"5": {
|
||||
id: "5", name: "Orchid Elegance", price: "300,000 so'm", description: "Ekzotik orkideyalardan tayyorlangan, murassa va yuqori dadning belgisi buket.", images: [
|
||||
"http://img.b2bpic.net/free-photo/beautifully-wrapped-gift-bouquet-roses_169016-8520.jpg?_wi=2", "http://img.b2bpic.net/free-photo/side-view-yellow-red-tulip-flower-grey_140725-12248.jpg?_wi=2"],
|
||||
category: "Orkideya", rating: 5.0,
|
||||
reviews: 23,
|
||||
details: [
|
||||
"10+ orkideya", "Ekzotik rang", "Premium qadri", "Davom etuvchi xush hid"],
|
||||
},
|
||||
"6": {
|
||||
id: "6", name: "Dahlia Dream", price: "200,000 so'm", description: "Gʻamrasin dalialari, ranglariga va shakllanishiga ega, go'zal buket.", images: [
|
||||
"http://img.b2bpic.net/free-photo/side-view-yellow-red-tulip-flower-grey_140725-12248.jpg?_wi=2", "http://img.b2bpic.net/free-photo/top-view-sunflowers-frame-with-copy-space_23-2150250788.jpg?_wi=2"],
|
||||
category: "Dalialar", rating: 4.5,
|
||||
reviews: 28,
|
||||
details: [
|
||||
"15+ dahlia", "Turli rang", "Rang tutgan", "Chiroyli qadri"],
|
||||
},
|
||||
"7": {
|
||||
id: "7", name: "Mixed Spring", price: "240,000 so'm", description: "Bahor gullarining aralashmasi, tabiatning go'zalligini o'zida ifodalovchi buket.", images: [
|
||||
"http://img.b2bpic.net/free-photo/top-view-sunflowers-frame-with-copy-space_23-2150250788.jpg?_wi=2", "http://img.b2bpic.net/free-photo/side-view-bouquet-peach-cream-color-roses-with-asparagus-grey-wooden-background_141793-7974.jpg?_wi=2"],
|
||||
category: "Aralash", rating: 4.6,
|
||||
reviews: 37,
|
||||
details: [
|
||||
"30+ turli gullar", "Rang harmoniyasi", "Bahor hissiyoti", "Professional surattirish"],
|
||||
},
|
||||
"8": {
|
||||
id: "8", name: "Premium Exotic", price: "320,000 so'm", description: "Ekzotik gullarning premium jamiyati, eng yuqori sifat va dizayn standartlari.", images: [
|
||||
"http://img.b2bpic.net/free-photo/side-view-bouquet-peach-cream-color-roses-with-asparagus-grey-wooden-background_141793-7974.jpg?_wi=2", "http://img.b2bpic.net/free-photo/beautifully-wrapped-gift-bouquet-roses_169016-8520.jpg?_wi=2"],
|
||||
category: "Ekzotik", rating: 4.9,
|
||||
reviews: 19,
|
||||
details: [
|
||||
"20+ ekzotik gullar", "Premium qadri", "Master florist dizayn", "Saqlanish davomi 7+ kun"],
|
||||
},
|
||||
};
|
||||
|
||||
export default function ProductDetailPage({
|
||||
params,
|
||||
}: {
|
||||
params: { id: string };
|
||||
}) {
|
||||
const product = products[params.id];
|
||||
const [isFavorited, setIsFavorited] = useState(false);
|
||||
const [mainImage, setMainImage] = useState(0);
|
||||
const [quantity, setQuantity] = useState(1);
|
||||
|
||||
if (!product) {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-shift"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="mediumSmall"
|
||||
sizing="mediumLarge"
|
||||
background="circleGradient"
|
||||
cardStyle="subtle-shadow"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
brandName="Fatinur Flowers"
|
||||
navItems={[
|
||||
{ name: "Бош сахифа", id: "/" },
|
||||
{ name: "Каталог", id: "/catalog" },
|
||||
{ name: "Категорияlar", id: "#features" },
|
||||
{ name: "Биз хақимизда", id: "#about" },
|
||||
{ name: "Aloqa", id: "#contact" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div className="py-20 text-center">Mahsulot topilmadi</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-shift"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="mediumSmall"
|
||||
sizing="mediumLarge"
|
||||
background="circleGradient"
|
||||
cardStyle="subtle-shadow"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
brandName="Fatinur Flowers"
|
||||
navItems={[
|
||||
{ name: "Бош сахифа", id: "/" },
|
||||
{ name: "Каталог", id: "/catalog" },
|
||||
{ name: "Категорияlar", id: "#features" },
|
||||
{ name: "Биз хақимизда", id: "#about" },
|
||||
{ name: "Aloqa", id: "#contact" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="py-20 px-4">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-12">
|
||||
{/* Product Images */}
|
||||
<div>
|
||||
<div className="bg-card rounded-lg overflow-hidden mb-4 aspect-square">
|
||||
<img
|
||||
src={product.images[mainImage]}
|
||||
alt={product.name}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
{product.images.map((img: string, idx: number) => (
|
||||
<button
|
||||
key={idx}
|
||||
onClick={() => setMainImage(idx)}
|
||||
className={`w-20 h-20 rounded-lg overflow-hidden border-2 transition-all ${
|
||||
mainImage === idx
|
||||
? "border-primary-cta"
|
||||
: "border-foreground/20 hover:border-foreground/40"
|
||||
}`}
|
||||
>
|
||||
<img
|
||||
src={img}
|
||||
alt={`Thumbnail ${idx}`}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Product Details */}
|
||||
<div>
|
||||
<div className="mb-4">
|
||||
<span className="text-sm text-primary-cta font-medium">
|
||||
{product.category}
|
||||
</span>
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold mb-4">{product.name}</h1>
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<div className="flex text-yellow-400">
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<span key={i}>
|
||||
{i < Math.floor(product.rating) ? "★" : "☆"}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<span className="text-foreground/75">
|
||||
{product.rating} ({product.reviews} sharhlar)
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-2xl font-bold text-primary-cta mb-4">
|
||||
{product.price}
|
||||
</p>
|
||||
<p className="text-foreground/75 mb-8 text-lg">
|
||||
{product.description}
|
||||
</p>
|
||||
|
||||
{/* Details List */}
|
||||
<div className="mb-8">
|
||||
<h3 className="font-bold mb-4">Mahsulot xususiyatlari:</h3>
|
||||
<ul className="space-y-2">
|
||||
{product.details.map((detail: string, idx: number) => (
|
||||
<li key={idx} className="flex items-center gap-3">
|
||||
<span className="text-primary-cta">✓</span>
|
||||
<span>{detail}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Quantity and Actions */}
|
||||
<div className="mb-8">
|
||||
<label className="block text-sm font-medium mb-2">Miqdor:</label>
|
||||
<div className="flex items-center gap-4 mb-6">
|
||||
<button
|
||||
onClick={() => setQuantity(Math.max(1, quantity - 1))}
|
||||
className="px-4 py-2 bg-card rounded-lg hover:bg-foreground/10 transition"
|
||||
>
|
||||
−
|
||||
</button>
|
||||
<span className="text-xl font-bold w-8 text-center">
|
||||
{quantity}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => setQuantity(quantity + 1)}
|
||||
className="px-4 py-2 bg-card rounded-lg hover:bg-foreground/10 transition"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="space-y-3">
|
||||
<button className="w-full py-3 bg-primary-cta text-background rounded-lg font-bold hover:opacity-90 transition">
|
||||
Savatchaga qo'shish
|
||||
</button>
|
||||
<div className="flex gap-3">
|
||||
<button
|
||||
onClick={() => setIsFavorited(!isFavorited)}
|
||||
className={`flex-1 py-3 border-2 rounded-lg font-bold transition ${
|
||||
isFavorited
|
||||
? "bg-primary-cta border-primary-cta text-background"
|
||||
: "border-foreground/30 hover:border-foreground/50"
|
||||
}`}
|
||||
>
|
||||
<Heart className="w-5 h-5 inline mr-2" />
|
||||
{isFavorited ? "Sevkili" : "Sevkilarga qo'sh"}
|
||||
</button>
|
||||
<button className="flex-1 py-3 border-2 border-foreground/30 rounded-lg font-bold hover:border-foreground/50 transition">
|
||||
<Share2 className="w-5 h-5 inline mr-2" />
|
||||
Ulashish
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Shipping Info */}
|
||||
<div className="mt-8 space-y-4 pt-8 border-t border-foreground/10">
|
||||
<div className="flex items-start gap-3">
|
||||
<Truck className="w-5 h-5 text-primary-cta mt-1" />
|
||||
<div>
|
||||
<p className="font-bold">Tez Yetkazib Berish</p>
|
||||
<p className="text-sm text-foreground/75">
|
||||
Toshkent bo'ylab 2 soatda yetkazib berishni taklif etamiz
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<Shield className="w-5 h-5 text-primary-cta mt-1" />
|
||||
<div>
|
||||
<p className="font-bold">Sifat Kafolati</p>
|
||||
<p className="text-sm text-foreground/75">
|
||||
Eng sifatli gullar yoki pul qaytarish
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<RotateCcw className="w-5 h-5 text-primary-cta mt-1" />
|
||||
<div>
|
||||
<p className="font-bold">Oson Qaytarish</p>
|
||||
<p className="text-sm text-foreground/75">
|
||||
7 kunlik qaytarish siyosati
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Fatinur Flowers"
|
||||
columns={[
|
||||
{
|
||||
title: "Mahsulotlar", items: [
|
||||
{ label: "Gullar katalogi", href: "/catalog" },
|
||||
{ label: "Eng mashhur buketlar", href: "/" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Kompaniya", items: [
|
||||
{ label: "Biз haqimizda", href: "/#about" },
|
||||
{ label: "Aloqa", href: "/#contact" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Aloqa", items: [
|
||||
{ label: "Telegram", href: "https://t.me/fatinur_flowers" },
|
||||
{ label: "Instagram", href: "https://instagram.com/fatinur_flowers" },
|
||||
],
|
||||
},
|
||||
]}
|
||||
copyrightText="© 2025 Fatinur Flowers. Barcha huquqlar himoyalangan."
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
147
src/app/catalog/page.tsx
Normal file
147
src/app/catalog/page.tsx
Normal file
@@ -0,0 +1,147 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import ProductCardOne from "@/components/sections/product/ProductCardOne";
|
||||
import FooterBaseCard from "@/components/sections/footer/FooterBaseCard";
|
||||
|
||||
const allProducts = [
|
||||
{
|
||||
id: "1", name: "Qizil Roza Buket", price: "250,000 so'm", imageSrc: "http://img.b2bpic.net/free-photo/beautifully-wrapped-gift-bouquet-roses_169016-8520.jpg?_wi=2", imageAlt: "Premium red rose bouquet", category: "roses", onProductClick: () => (window.location.href = "/catalog/1"),
|
||||
},
|
||||
{
|
||||
id: "2", name: "Tula Aralash", price: "180,000 so'm", imageSrc: "http://img.b2bpic.net/free-photo/side-view-yellow-red-tulip-flower-grey_140725-12248.jpg?_wi=2", imageAlt: "Colorful mixed tulip arrangement", category: "tulips", onProductClick: () => (window.location.href = "/catalog/2"),
|
||||
},
|
||||
{
|
||||
id: "3", name: "Oyoq Buket", price: "220,000 so'm", imageSrc: "http://img.b2bpic.net/free-photo/top-view-sunflowers-frame-with-copy-space_23-2150250788.jpg?_wi=2", imageAlt: "Bright sunflower bouquet", category: "sunflowers", onProductClick: () => (window.location.href = "/catalog/3"),
|
||||
},
|
||||
{
|
||||
id: "4", name: "Oq Lililar", price: "280,000 so'm", imageSrc: "http://img.b2bpic.net/free-photo/side-view-bouquet-peach-cream-color-roses-with-asparagus-grey-wooden-background_141793-7974.jpg?_wi=2", imageAlt: "Elegant white lily arrangement", category: "lilies", onProductClick: () => (window.location.href = "/catalog/4"),
|
||||
},
|
||||
{
|
||||
id: "5", name: "Orchid Elegance", price: "300,000 so'm", imageSrc: "http://img.b2bpic.net/free-photo/beautifully-wrapped-gift-bouquet-roses_169016-8520.jpg?_wi=2", imageAlt: "Elegant orchid bouquet", category: "orchids", onProductClick: () => (window.location.href = "/catalog/5"),
|
||||
},
|
||||
{
|
||||
id: "6", name: "Dahlia Dream", price: "200,000 so'm", imageSrc: "http://img.b2bpic.net/free-photo/side-view-yellow-red-tulip-flower-grey_140725-12248.jpg?_wi=2", imageAlt: "Beautiful dahlia arrangement", category: "dahlias", onProductClick: () => (window.location.href = "/catalog/6"),
|
||||
},
|
||||
{
|
||||
id: "7", name: "Mixed Spring", price: "240,000 so'm", imageSrc: "http://img.b2bpic.net/free-photo/top-view-sunflowers-frame-with-copy-space_23-2150250788.jpg?_wi=2", imageAlt: "Mixed spring flowers", category: "mixed", onProductClick: () => (window.location.href = "/catalog/7"),
|
||||
},
|
||||
{
|
||||
id: "8", name: "Premium Exotic", price: "320,000 so'm", imageSrc: "http://img.b2bpic.net/free-photo/side-view-bouquet-peach-cream-color-roses-with-asparagus-grey-wooden-background_141793-7974.jpg?_wi=2", imageAlt: "Premium exotic bouquet", category: "exotic", onProductClick: () => (window.location.href = "/catalog/8"),
|
||||
},
|
||||
];
|
||||
|
||||
const categories = [
|
||||
{ id: "all", name: "Barchasi" },
|
||||
{ id: "roses", name: "Rozalar" },
|
||||
{ id: "tulips", name: "Tulalar" },
|
||||
{ id: "sunflowers", name: "Oyoqlar" },
|
||||
{ id: "lilies", name: "Lililar" },
|
||||
{ id: "orchids", name: "Orkideya" },
|
||||
{ id: "dahlias", name: "Dalialar" },
|
||||
{ id: "mixed", name: "Aralash" },
|
||||
{ id: "exotic", name: "Ekzotik" },
|
||||
];
|
||||
|
||||
export default function CatalogPage() {
|
||||
const [selectedCategory, setSelectedCategory] = useState("all");
|
||||
|
||||
const filteredProducts =
|
||||
selectedCategory === "all"
|
||||
? allProducts
|
||||
: allProducts.filter((product) => product.category === selectedCategory);
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-shift"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="mediumSmall"
|
||||
sizing="mediumLarge"
|
||||
background="circleGradient"
|
||||
cardStyle="subtle-shadow"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
brandName="Fatinur Flowers"
|
||||
navItems={[
|
||||
{ name: "Бош сахифа", id: "/" },
|
||||
{ name: "Каталог", id: "/catalog" },
|
||||
{ name: "Категорияlar", id: "#features" },
|
||||
{ name: "Биз хақимизда", id: "#about" },
|
||||
{ name: "Aloqa", id: "#contact" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="py-20 px-4">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<h1 className="text-5xl font-bold text-center mb-4">Gullar Katalogi</h1>
|
||||
<p className="text-center text-lg text-foreground/75 mb-12">
|
||||
Bizning eng chiroyli buketlarni kategoriya bo'yicha tanlang
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap gap-3 justify-center mb-12">
|
||||
{categories.map((category) => (
|
||||
<button
|
||||
key={category.id}
|
||||
onClick={() => setSelectedCategory(category.id)}
|
||||
className={`px-6 py-2 rounded-full font-medium transition-all ${
|
||||
selectedCategory === category.id
|
||||
? "bg-primary-cta text-background"
|
||||
: "bg-card text-foreground border border-foreground/20 hover:border-foreground/40"
|
||||
}`}
|
||||
>
|
||||
{category.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="products" data-section="products">
|
||||
<ProductCardOne
|
||||
title={selectedCategory === "all" ? "Barchasi" : categories.find(c => c.id === selectedCategory)?.name}
|
||||
description="Har bir buket sifat va sevgi bilan tayyorlanadi"
|
||||
products={filteredProducts}
|
||||
gridVariant="four-items-2x2-equal-grid"
|
||||
animationType="slide-up"
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Fatinur Flowers"
|
||||
columns={[
|
||||
{
|
||||
title: "Mahsulotlar", items: [
|
||||
{ label: "Gullar katalogi", href: "/catalog" },
|
||||
{ label: "Eng mashhur buketlar", href: "/" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Kompaniya", items: [
|
||||
{ label: "Biз haqimizda", href: "/#about" },
|
||||
{ label: "Aloqa", href: "/#contact" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Aloqa", items: [
|
||||
{ label: "Telegram", href: "https://t.me/fatinur_flowers" },
|
||||
{ label: "Instagram", href: "https://instagram.com/fatinur_flowers" },
|
||||
],
|
||||
},
|
||||
]}
|
||||
copyrightText="© 2025 Fatinur Flowers. Barcha huquqlar himoyalangan."
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
251
src/app/checkout/page.tsx
Normal file
251
src/app/checkout/page.tsx
Normal file
@@ -0,0 +1,251 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import FooterBaseCard from "@/components/sections/footer/FooterBaseCard";
|
||||
import { useState } from "react";
|
||||
import Input from "@/components/form/Input";
|
||||
|
||||
interface OrderFormData {
|
||||
fullName: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
address: string;
|
||||
city: string;
|
||||
postalCode: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export default function CheckoutPage() {
|
||||
const [formData, setFormData] = useState<OrderFormData>({
|
||||
fullName: "", email: "", phone: "", address: "", city: "", postalCode: "", message: ""});
|
||||
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [submitStatus, setSubmitStatus] = useState<"idle" | "success" | "error">("idle");
|
||||
|
||||
const handleInputChange = (field: keyof OrderFormData, value: string) => {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[field]: value,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setIsSubmitting(true);
|
||||
setSubmitStatus("idle");
|
||||
|
||||
try {
|
||||
// Save order to database via API
|
||||
const response = await fetch("/api/orders", {
|
||||
method: "POST", headers: {
|
||||
"Content-Type": "application/json"},
|
||||
body: JSON.stringify(formData),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to submit order");
|
||||
}
|
||||
|
||||
setSubmitStatus("success");
|
||||
setFormData({
|
||||
fullName: "", email: "", phone: "", address: "", city: "", postalCode: "", message: ""});
|
||||
|
||||
setTimeout(() => {
|
||||
setSubmitStatus("idle");
|
||||
}, 3000);
|
||||
} catch (error) {
|
||||
console.error("Error submitting order:", error);
|
||||
setSubmitStatus("error");
|
||||
|
||||
setTimeout(() => {
|
||||
setSubmitStatus("idle");
|
||||
}, 3000);
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-shift"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="mediumSmall"
|
||||
sizing="mediumLarge"
|
||||
background="circleGradient"
|
||||
cardStyle="subtle-shadow"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
brandName="Fatinur Flowers"
|
||||
navItems={[
|
||||
{ name: "Бош сахифа", id: "/" },
|
||||
{ name: "Каталог", id: "products" },
|
||||
{ name: "Категорияlar", id: "features" },
|
||||
{ name: "Биз хақимизда", id: "about" },
|
||||
{ name: "Aloqa", id: "contact" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="min-h-screen py-20 px-4">
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<div className="mb-12">
|
||||
<h1 className="text-4xl md:text-5xl font-extrabold mb-4">
|
||||
Buyurtmani Rasmiylash
|
||||
</h1>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-400">
|
||||
Quyidagi shaklni to'ldiring va buyurtmangizni tasdiqlang. Biz tez orada siz bilan bog'lanamiz.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{/* Customer Information */}
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-2xl font-semibold mb-4">Shaxsiy Ma'lumot</h2>
|
||||
|
||||
<Input
|
||||
value={formData.fullName}
|
||||
onChange={(value) => handleInputChange("fullName", value)}
|
||||
type="text"
|
||||
placeholder="To'liq Ismingiz"
|
||||
required
|
||||
/>
|
||||
|
||||
<Input
|
||||
value={formData.email}
|
||||
onChange={(value) => handleInputChange("email", value)}
|
||||
type="email"
|
||||
placeholder="Email Manzili"
|
||||
required
|
||||
/>
|
||||
|
||||
<Input
|
||||
value={formData.phone}
|
||||
onChange={(value) => handleInputChange("phone", value)}
|
||||
type="tel"
|
||||
placeholder="Telefon Raqami (+998...)"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Delivery Information */}
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-2xl font-semibold mb-4">Yetkazib Berish Manzili</h2>
|
||||
|
||||
<Input
|
||||
value={formData.address}
|
||||
onChange={(value) => handleInputChange("address", value)}
|
||||
type="text"
|
||||
placeholder="Manzil (Ko'cha, uy raqami)"
|
||||
required
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<Input
|
||||
value={formData.city}
|
||||
onChange={(value) => handleInputChange("city", value)}
|
||||
type="text"
|
||||
placeholder="Shahar"
|
||||
required
|
||||
/>
|
||||
|
||||
<Input
|
||||
value={formData.postalCode}
|
||||
onChange={(value) => handleInputChange("postalCode", value)}
|
||||
type="text"
|
||||
placeholder="Pochtali Kod"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Additional Message */}
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-2xl font-semibold mb-4">Qo'shimcha Xabar</h2>
|
||||
<textarea
|
||||
value={formData.message}
|
||||
onChange={(e) => handleInputChange("message", e.target.value)}
|
||||
placeholder="Ustozga qo'shimcha so'zlar yoki taklif (ixtiyoriy)"
|
||||
rows={4}
|
||||
className="w-full px-4 py-3 rounded-lg bg-opacity-50 backdrop-blur-sm border border-opacity-20 focus:outline-none focus:ring-2 transition-all duration-300 placeholder-opacity-75"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Status Messages */}
|
||||
{submitStatus === "success" && (
|
||||
<div className="p-4 bg-green-100 dark:bg-green-900 border border-green-300 dark:border-green-700 rounded-lg text-green-800 dark:text-green-100">
|
||||
✓ Buyurtma muvaffaqiyatli qabul qilindi! Biz tez orada siz bilan bog'lanamiz.
|
||||
</div>
|
||||
)}
|
||||
|
||||
{submitStatus === "error" && (
|
||||
<div className="p-4 bg-red-100 dark:bg-red-900 border border-red-300 dark:border-red-700 rounded-lg text-red-800 dark:text-red-100">
|
||||
✗ Xatolik yuz berdi. Iltimos, qayta urinib ko'ring.
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Submit Button */}
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className="w-full py-3 px-6 rounded-lg font-semibold text-white bg-gradient-to-r from-pink-500 to-rose-500 hover:from-pink-600 hover:to-rose-600 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{isSubmitting ? "Yuborilmoqda..." : "Buyurtmani Tasdiqlash"}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div className="mt-8 p-6 rounded-lg bg-opacity-50 backdrop-blur-sm border border-opacity-20">
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
💬 Savollaringiz bo'lsa, biz bilan bog'laning:
|
||||
<br />
|
||||
📞 <a href="https://t.me/fatinur_flowers" className="text-pink-500 hover:text-pink-600 ml-2">Telegram</a>
|
||||
<a href="https://wa.me/998901234567" className="text-pink-500 hover:text-pink-600 ml-2">WhatsApp</a>
|
||||
<a href="https://instagram.com/fatinur_flowers" className="text-pink-500 hover:text-pink-600 ml-2">Instagram</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Fatinur Flowers"
|
||||
columns={[
|
||||
{
|
||||
title: "Mahsulotlar", items: [
|
||||
{ label: "Gullar katalogi", href: "#products" },
|
||||
{ label: "Kategoriyalar", href: "#features" },
|
||||
{ label: "Eng mashhur buketlar", href: "#products" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Kompaniya", items: [
|
||||
{ label: "Biз haqimizda", href: "#about" },
|
||||
{ label: "Yetkazib berish", href: "#contact" },
|
||||
{ label: "Aloqa", href: "#contact" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Aloqa", items: [
|
||||
{ label: "Telegram", href: "https://t.me/fatinur_flowers" },
|
||||
{ label: "Instagram", href: "https://instagram.com/fatinur_flowers" },
|
||||
{ label: "WhatsApp", href: "https://wa.me/998901234567" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Qonuniy", items: [
|
||||
{ label: "Maxfiylik siyosati", href: "#" },
|
||||
{ label: "Foydalanish shartlari", href: "#" },
|
||||
{ label: "Kukilar siyosati", href: "#" },
|
||||
],
|
||||
},
|
||||
]}
|
||||
copyrightText="© 2025 Fatinur Flowers. Barcha huquqlar himoyalangan."
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
101
src/app/contact/page.tsx
Normal file
101
src/app/contact/page.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import ContactText from "@/components/sections/contact/ContactText";
|
||||
import SocialProofOne from "@/components/sections/socialProof/SocialProofOne";
|
||||
import FooterBaseCard from "@/components/sections/footer/FooterBaseCard";
|
||||
|
||||
export default function ContactPage() {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-shift"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="mediumSmall"
|
||||
sizing="mediumLarge"
|
||||
background="circleGradient"
|
||||
cardStyle="subtle-shadow"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
brandName="Fatinur Flowers"
|
||||
navItems={[
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Catalog", id: "/catalog" },
|
||||
{ name: "About", id: "/about" },
|
||||
{ name: "Delivery", id: "/delivery" },
|
||||
{ name: "Contact", id: "/contact" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="contact-section" data-section="contact" className="pt-20">
|
||||
<ContactText
|
||||
text="Get in touch with Fatinur Flowers. We're here to help you express your love and beauty through flowers."
|
||||
animationType="entrance-slide"
|
||||
buttons={[
|
||||
{ text: "Order on Telegram", href: "https://t.me/fatinur_flowers" },
|
||||
{ text: "Message on Instagram", href: "https://instagram.com/fatinur_flowers" },
|
||||
{ text: "WhatsApp", href: "https://wa.me/998901234567" },
|
||||
]}
|
||||
background={{ variant: "plain" }}
|
||||
useInvertedBackground={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="social" data-section="social">
|
||||
<SocialProofOne
|
||||
title="Connect With Us"
|
||||
description="Follow us on social media for daily flower inspiration and special offers"
|
||||
tag="📱 Social Links"
|
||||
names={["Telegram", "Instagram", "WhatsApp", "Facebook"]}
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={false}
|
||||
speed={40}
|
||||
showCard={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Fatinur Flowers"
|
||||
columns={[
|
||||
{
|
||||
title: "Products", items: [
|
||||
{ label: "Flower Catalog", href: "/catalog" },
|
||||
{ label: "Categories", href: "/catalog" },
|
||||
{ label: "Popular Bouquets", href: "/catalog" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About Us", href: "/about" },
|
||||
{ label: "Delivery Info", href: "/delivery" },
|
||||
{ label: "Contact", href: "/contact" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Connect", items: [
|
||||
{ label: "Telegram", href: "https://t.me/fatinur_flowers" },
|
||||
{ label: "Instagram", href: "https://instagram.com/fatinur_flowers" },
|
||||
{ label: "WhatsApp", href: "https://wa.me/998901234567" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Legal", items: [
|
||||
{ label: "Privacy Policy", href: "/privacy" },
|
||||
{ label: "Terms of Service", href: "/terms" },
|
||||
{ label: "Cookie Policy", href: "/cookies" },
|
||||
],
|
||||
},
|
||||
]}
|
||||
copyrightText="© 2025 Fatinur Flowers. All rights reserved."
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
96
src/app/delivery/page.tsx
Normal file
96
src/app/delivery/page.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import FeatureBento from "@/components/sections/feature/FeatureBento";
|
||||
import FooterBaseCard from "@/components/sections/footer/FooterBaseCard";
|
||||
import { MapPin, Clock, ShieldCheck } from "lucide-react";
|
||||
|
||||
export default function DeliveryPage() {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-shift"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="mediumSmall"
|
||||
sizing="mediumLarge"
|
||||
background="circleGradient"
|
||||
cardStyle="subtle-shadow"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="layered"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
brandName="Fatinur Flowers"
|
||||
navItems={[
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "Catalog", id: "/catalog" },
|
||||
{ name: "About", id: "/about" },
|
||||
{ name: "Delivery", id: "/delivery" },
|
||||
{ name: "Contact", id: "/contact" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="delivery" data-section="delivery" className="pt-20">
|
||||
<FeatureBento
|
||||
title="Fast & Reliable Delivery"
|
||||
description="We ensure your flowers arrive fresh and beautiful, on time, every time."
|
||||
tag="🚚 Delivery Information"
|
||||
features={[
|
||||
{
|
||||
title: "2-Hour Delivery", description: "Express delivery available throughout the city", bentoComponent: "reveal-icon", icon: Clock,
|
||||
},
|
||||
{
|
||||
title: "Tracked Delivery", description: "Real-time tracking of your flower delivery", bentoComponent: "reveal-icon", icon: MapPin,
|
||||
},
|
||||
{
|
||||
title: "Guaranteed Quality", description: "Fresh flowers guaranteed or your money back", bentoComponent: "reveal-icon", icon: ShieldCheck,
|
||||
},
|
||||
]}
|
||||
textboxLayout="default"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseCard
|
||||
logoText="Fatinur Flowers"
|
||||
columns={[
|
||||
{
|
||||
title: "Products", items: [
|
||||
{ label: "Flower Catalog", href: "/catalog" },
|
||||
{ label: "Categories", href: "/catalog" },
|
||||
{ label: "Popular Bouquets", href: "/catalog" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About Us", href: "/about" },
|
||||
{ label: "Delivery Info", href: "/delivery" },
|
||||
{ label: "Contact", href: "/contact" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Connect", items: [
|
||||
{ label: "Telegram", href: "https://t.me/fatinur_flowers" },
|
||||
{ label: "Instagram", href: "https://instagram.com/fatinur_flowers" },
|
||||
{ label: "WhatsApp", href: "https://wa.me/998901234567" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Legal", items: [
|
||||
{ label: "Privacy Policy", href: "/privacy" },
|
||||
{ label: "Terms of Service", href: "/terms" },
|
||||
{ label: "Cookie Policy", href: "/cookies" },
|
||||
],
|
||||
},
|
||||
]}
|
||||
copyrightText="© 2025 Fatinur Flowers. All rights reserved."
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
@@ -1,57 +1,17 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Halant } from "next/font/google";
|
||||
import { Inter } from "next/font/google";
|
||||
import { Manrope } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import { ServiceWrapper } from "@/components/ServiceWrapper";
|
||||
import Tag from "@/tag/Tag";
|
||||
|
||||
const halant = Halant({
|
||||
variable: "--font-halant", subsets: ["latin"],
|
||||
weight: ["300", "400", "500", "600", "700"],
|
||||
});
|
||||
|
||||
const inter = Inter({
|
||||
variable: "--font-inter", subsets: ["latin"],
|
||||
});
|
||||
|
||||
const manrope = Manrope({
|
||||
variable: "--font-manrope", subsets: ["latin"],
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Fatinur Flowers | Premium Gul Do'koni Toshkent", description: "Fatinur Flowers – eng sifatli va yangi gullar. Tez yetkazib berish, professional dizayn va sevgi bilan tayyorlangan buketlar.", keywords: "gullar, buket, sevgi, gul do'koni, Toshkent, yetkazib berish, rossali, oq roza, qizil roza, tula", metadataBase: new URL("https://fatinur-flowers.uz"),
|
||||
alternates: {
|
||||
canonical: "https://fatinur-flowers.uz"},
|
||||
openGraph: {
|
||||
title: "Fatinur Flowers | Premium Gul Do'koni", description: "Har bir lahza uchun eng chiroyli gullar. Tez yetkazib berish va professional florist xizmati.", url: "https://fatinur-flowers.uz", siteName: "Fatinur Flowers", images: [
|
||||
{
|
||||
url: "http://img.b2bpic.net/free-photo/brunette-girl-red-buy-flowers-flower-store_627829-9126.jpg", alt: "Fatinur Flowers Premium Bouquet"},
|
||||
],
|
||||
type: "website"},
|
||||
twitter: {
|
||||
card: "summary_large_image", title: "Fatinur Flowers | Premium Gul Do'koni", description: "Har bir lahza uchun eng chiroyli gullar", images: ["http://img.b2bpic.net/free-photo/brunette-girl-red-buy-flowers-flower-store_627829-9126.jpg"],
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
title: "Fatinur Flowers", description: "Premium flower delivery service"};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
}) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<ServiceWrapper>
|
||||
<body
|
||||
className={`${halant.variable} ${inter.variable} ${manrope.variable} antialiased`}
|
||||
>
|
||||
<Tag />
|
||||
{children}
|
||||
|
||||
<html lang="en">
|
||||
<body>{children}
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
@@ -1419,7 +1379,6 @@ export default function RootLayout({
|
||||
}}
|
||||
/>
|
||||
</body>
|
||||
</ServiceWrapper>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -30,11 +30,12 @@ export default function LandingPage() {
|
||||
<NavbarStyleApple
|
||||
brandName="Fatinur Flowers"
|
||||
navItems={[
|
||||
{ name: "Бош сахифа", id: "hero" },
|
||||
{ name: "Бош сахифа", id: "/" },
|
||||
{ name: "Каталог", id: "products" },
|
||||
{ name: "Категорияlar", id: "features" },
|
||||
{ name: "Биз хақимизда", id: "about" },
|
||||
{ name: "Aloqa", id: "contact" },
|
||||
{ name: "Admin", id: "/admin" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@ html {
|
||||
body {
|
||||
background-color: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: var(--font-manrope), sans-serif;
|
||||
font-family: var(--font-poppins), sans-serif;
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
overscroll-behavior: none;
|
||||
@@ -24,5 +24,5 @@ h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: var(--font-manrope), sans-serif;
|
||||
font-family: var(--font-poppins), sans-serif;
|
||||
}
|
||||
|
||||
@@ -10,15 +10,15 @@
|
||||
--accent: #ffffff;
|
||||
--background-accent: #ffffff; */
|
||||
|
||||
--background: #f5f5f5;
|
||||
--background: #faf8f5;
|
||||
--card: #ffffff;
|
||||
--foreground: #1c1c1c;
|
||||
--primary-cta: #1f514c;
|
||||
--foreground: #2d1b1f;
|
||||
--primary-cta: #d4606b;
|
||||
--primary-cta-text: #f5f5f5;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1c1c1c;
|
||||
--accent: #159c49;
|
||||
--background-accent: #a8e8ba;
|
||||
--accent: #7dd3a0;
|
||||
--background-accent: #e8d4d9;
|
||||
|
||||
/* text sizing - set by ThemeProvider */
|
||||
/* --text-2xs: clamp(0.465rem, 0.62vw, 0.62rem);
|
||||
|
||||
Reference in New Issue
Block a user