feat: interactive pages migrated to Next.js (Dashboard, Checkout, Profile, Wiki)
This commit is contained in:
parent
3de0408e6f
commit
976dfcd610
5
frontend/application/app/checkout/page.tsx
Normal file
5
frontend/application/app/checkout/page.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import CheckoutPage from "../../components/CheckoutPage";
|
||||
|
||||
export default function Checkout() {
|
||||
return <CheckoutPage />;
|
||||
}
|
||||
5
frontend/application/app/dashboard/page.tsx
Normal file
5
frontend/application/app/dashboard/page.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import UserDashboard from "../../components/UserDashboard";
|
||||
|
||||
export default function DashboardPage() {
|
||||
return <UserDashboard />;
|
||||
}
|
||||
5
frontend/application/app/profile/page.tsx
Normal file
5
frontend/application/app/profile/page.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import PetProfile from "../../components/PetProfile";
|
||||
|
||||
export default function ProfilePage() {
|
||||
return <PetProfile />;
|
||||
}
|
||||
5
frontend/application/app/wiki/page.tsx
Normal file
5
frontend/application/app/wiki/page.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import IngredientWiki from "../../components/IngredientWiki";
|
||||
|
||||
export default function WikiPage() {
|
||||
return <IngredientWiki />;
|
||||
}
|
||||
@ -23,8 +23,10 @@ import { useUserStore } from "../store/userStore";
|
||||
import { Product } from "../data/products";
|
||||
import { productService } from "../services/productService";
|
||||
import { toast } from "sonner";
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
export default function CheckoutPage({ onBack, onComplete }: { onBack: () => void; onComplete: (orderId: string) => void }) {
|
||||
export default function CheckoutPage() {
|
||||
const router = useRouter();
|
||||
const { items, getTotal, getSubtotal, getDiscount, isSubscribed, charityDonation, setCharityDonation, addOrder, clearCart } = useCartStore();
|
||||
const { getActivePet, updatePet } = usePetStore();
|
||||
const { profile, updateProfile } = useUserStore();
|
||||
@ -94,8 +96,8 @@ export default function CheckoutPage({ onBack, onComplete }: { onBack: () => voi
|
||||
}
|
||||
|
||||
clearCart();
|
||||
onComplete(orderId);
|
||||
toast.success("سفارش شما با موفقیت ثبت شد و به پرونده سلامت همدمتان اضافه شد!");
|
||||
router.push('/dashboard');
|
||||
} catch (err: any) {
|
||||
toast.error(err.message || "خطا در ثبت سفارش. لطفاً مجدداً تلاش کنید.");
|
||||
} finally {
|
||||
@ -111,7 +113,7 @@ export default function CheckoutPage({ onBack, onComplete }: { onBack: () => voi
|
||||
<ShieldCheck className="w-12 h-12" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-black text-medical-gray-900 italic">سبد خرید شما خالی است</h2>
|
||||
<button onClick={onBack} className="text-canina-blue font-black underline underline-offset-8">بازگشت به فروشگاه</button>
|
||||
<button onClick={() => router.push('/shop')} className="text-canina-blue font-black underline underline-offset-8">بازگشت به فروشگاه</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -124,7 +126,7 @@ export default function CheckoutPage({ onBack, onComplete }: { onBack: () => voi
|
||||
{/* Mobile Navigation & Breadcrumbs */}
|
||||
<div className="lg:hidden mb-10 space-y-4">
|
||||
<button
|
||||
onClick={onBack}
|
||||
onClick={() => router.back()}
|
||||
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
|
||||
>
|
||||
<ChevronRight className="w-5 h-5" />
|
||||
@ -132,7 +134,7 @@ export default function CheckoutPage({ onBack, onComplete }: { onBack: () => voi
|
||||
</button>
|
||||
|
||||
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest overflow-x-auto whitespace-nowrap pb-2">
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={onBack}>سبد خرید</span>
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/shop')}>سبد خرید</span>
|
||||
<ChevronLeft className="w-2.5 h-2.5" />
|
||||
<span className="text-canina-blue">نهاییسازی سفارش</span>
|
||||
</div>
|
||||
@ -140,7 +142,7 @@ export default function CheckoutPage({ onBack, onComplete }: { onBack: () => voi
|
||||
|
||||
{/* Desktop Breadcrumbs (Hidden on Mobile) */}
|
||||
<div className="hidden lg:flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={onBack}>خانه</span>
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
|
||||
<ChevronLeft className="w-2.5 h-2.5" />
|
||||
<span className="text-canina-blue">درگاه پرداخت امن و نهاییسازی</span>
|
||||
</div>
|
||||
|
||||
@ -6,7 +6,10 @@ import { FlaskConical, CheckCircle2, ChevronRight, ChevronLeft, Beaker } from "l
|
||||
import { useSettingsStore } from "../store/settingsStore";
|
||||
import { productService } from "../services/productService";
|
||||
|
||||
export default function IngredientWiki({ onProductClick, onBack }: { onProductClick: (p: Product) => void, onBack?: () => void }) {
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
export default function IngredientWiki() {
|
||||
const router = useRouter();
|
||||
const texts = useSettingsStore(state => state.texts);
|
||||
const [products, setProducts] = useState<Product[]>([]);
|
||||
|
||||
@ -33,7 +36,7 @@ export default function IngredientWiki({ onProductClick, onBack }: { onProductCl
|
||||
{/* Mobile Navigation & Breadcrumbs */}
|
||||
<div className="lg:hidden mb-12 space-y-4">
|
||||
<button
|
||||
onClick={onBack}
|
||||
onClick={() => router.back()}
|
||||
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
|
||||
>
|
||||
<ChevronRight className="w-5 h-5" />
|
||||
@ -41,7 +44,7 @@ export default function IngredientWiki({ onProductClick, onBack }: { onProductCl
|
||||
</button>
|
||||
|
||||
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest overflow-x-auto whitespace-nowrap pb-2">
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={onBack}>کانینا</span>
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>کانینا</span>
|
||||
<ChevronLeft className="w-2.5 h-2.5" />
|
||||
<span className="text-canina-blue">دانشنامه علمی</span>
|
||||
</div>
|
||||
@ -49,7 +52,7 @@ export default function IngredientWiki({ onProductClick, onBack }: { onProductCl
|
||||
|
||||
{/* Desktop Breadcrumbs */}
|
||||
<div className="hidden lg:flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-12">
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={onBack}>خانه</span>
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
|
||||
<ChevronLeft className="w-2.5 h-2.5" />
|
||||
<span className="text-canina-blue">دانشنامه مواد نایاب و ارگانیک</span>
|
||||
</div>
|
||||
@ -122,7 +125,7 @@ export default function IngredientWiki({ onProductClick, onBack }: { onProductCl
|
||||
{hasIngredient.length > 0 ? hasIngredient.map(p => (
|
||||
<div
|
||||
key={p.id}
|
||||
onClick={() => onProductClick(p)}
|
||||
onClick={() => router.push(`/shop/${p.id}`)}
|
||||
className="bg-white rounded-[2.5rem] p-6 shadow-xl hover:scale-105 transition-transform cursor-pointer group"
|
||||
>
|
||||
<img src={p.image} alt={p.name} className="w-24 h-24 object-contain mx-auto mb-4" referrerPolicy="no-referrer" />
|
||||
|
||||
@ -35,12 +35,13 @@ import SafeImage from "./SafeImage";
|
||||
import { toast } from "sonner";
|
||||
import { toPersian, cn } from "../lib/utils";
|
||||
|
||||
export default function PetProfile({ onProductClick, onBack, initialView, advisorNeed }: {
|
||||
onProductClick: (p: Product) => void,
|
||||
onBack?: () => void,
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
export default function PetProfile({ initialView, advisorNeed }: {
|
||||
initialView?: "index" | "detail" | "add" | "edit",
|
||||
advisorNeed?: string | null
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const { pets, activePetId, addPet, removePet, setActivePet, getActivePet, updatePet, addReminder, toggleReminder, addHealthLog } = usePetStore();
|
||||
const { orders } = useCartStore();
|
||||
const activePet = getActivePet();
|
||||
@ -553,7 +554,7 @@ export default function PetProfile({ onProductClick, onBack, initialView, adviso
|
||||
onClick={() => {
|
||||
if (view === "edit") setView("detail");
|
||||
else if (pets.length > 0) setView("index");
|
||||
else onBack?.();
|
||||
else router.back();
|
||||
}}
|
||||
className="absolute top-8 left-8 text-medical-gray-400 hover:text-canina-blue transition-colors text-[10px] font-black uppercase tracking-widest"
|
||||
>
|
||||
@ -757,7 +758,7 @@ export default function PetProfile({ onProductClick, onBack, initialView, adviso
|
||||
|
||||
{isLow && (
|
||||
<button
|
||||
onClick={() => onProductClick(product)}
|
||||
onClick={() => router.push(`/shop/${product.id}`)}
|
||||
className="w-full py-2 bg-red-500 text-white rounded-xl text-[10px] font-black uppercase tracking-widest hover:bg-red-600 transition-all flex items-center justify-center gap-2"
|
||||
>
|
||||
<Package className="w-3.5 h-3.5" />
|
||||
|
||||
@ -12,7 +12,10 @@ import AddressModal from "./AddressModal";
|
||||
import DeleteConfirmModal from "./DeleteConfirmModal";
|
||||
import TopUpModal from "./TopUpModal";
|
||||
|
||||
export default function UserDashboard({ onBack, onNavigate }: { onBack: () => void, onNavigate: (v: any) => void }) {
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
export default function UserDashboard() {
|
||||
const router = useRouter();
|
||||
const { profile, logout, addAddress, updateAddress, deleteAddress, setDefaultAddress, topUpWallet } = useUserStore();
|
||||
const { orders } = useCartStore();
|
||||
const [activeTab, setActiveTab] = React.useState<"profile" | "orders" | "wallet" | "addresses">("profile");
|
||||
@ -85,7 +88,7 @@ export default function UserDashboard({ onBack, onNavigate }: { onBack: () => vo
|
||||
|
||||
const handleLogout = () => {
|
||||
logout();
|
||||
onBack();
|
||||
router.push('/');
|
||||
};
|
||||
|
||||
const handleSaveAddress = async (addr: Address) => {
|
||||
@ -140,7 +143,7 @@ export default function UserDashboard({ onBack, onNavigate }: { onBack: () => vo
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Breadcrumb */}
|
||||
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-10">
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={onBack}>خانه</span>
|
||||
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
|
||||
<ChevronRight className="w-2.5 h-2.5" />
|
||||
<span className="text-canina-blue">پنل کاربری</span>
|
||||
</div>
|
||||
@ -380,7 +383,7 @@ export default function UserDashboard({ onBack, onNavigate }: { onBack: () => vo
|
||||
<div className="text-center py-20">
|
||||
<ShoppingBag className="w-16 h-16 text-medical-gray-200 mx-auto mb-4" />
|
||||
<p className="text-medical-gray-400 font-bold">هنوز سفارشی ثبت نکردهاید.</p>
|
||||
<button onClick={() => onNavigate("shop")} className="mt-6 text-canina-blue font-black underline underline-offset-8">برو به فروشگاه</button>
|
||||
<button onClick={() => router.push('/shop')} className="mt-6 text-canina-blue font-black underline underline-offset-8">برو به فروشگاه</button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user