174 lines
5.9 KiB
TypeScript
174 lines
5.9 KiB
TypeScript
"use client"
|
||
|
||
import type React from "react"
|
||
|
||
import { useState } from "react"
|
||
import { useRouter } from "next/navigation"
|
||
import { useCart } from "@/contexts/cart-context"
|
||
import { Button } from "@/components/ui/button"
|
||
import { Label } from "@/components/ui/label"
|
||
import { Textarea } from "@/components/ui/textarea"
|
||
import { CheckCircle2, ExternalLink } from "lucide-react"
|
||
import Cookies from "js-cookie"
|
||
|
||
const setTotalPriceCookie = (totalPrice: number) => {
|
||
Cookies.set("totalPrice", totalPrice.toString(), { expires: 1 }) // Expires in 1 day
|
||
}
|
||
|
||
export function CheckoutForm() {
|
||
const [address, setAddress] = useState("")
|
||
const [isProcessing, setIsProcessing] = useState(false)
|
||
const [isOrderPlaced, setIsOrderPlaced] = useState(false)
|
||
const [step, setStep] = useState(0)
|
||
const [paymentLink, setPaymentLink] = useState("")
|
||
const [error, setError] = useState<string | null>(null)
|
||
|
||
const router = useRouter()
|
||
const { items, clearCart, getTotalItems } = useCart()
|
||
|
||
const totalPrice = items.reduce((sum, item) => sum + item.price * item.quantity, 0)
|
||
|
||
const handleAddressSubmit = (e: React.FormEvent) => {
|
||
e.preventDefault()
|
||
if (address.trim()) {
|
||
setStep(1)
|
||
}
|
||
}
|
||
|
||
const handleInitiatePayment = async () => {
|
||
setIsProcessing(true)
|
||
setError(null)
|
||
try {
|
||
setTotalPriceCookie(totalPrice)
|
||
|
||
const response = await fetch("http://localhost:8081/api/pay", {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
},
|
||
body: JSON.stringify({
|
||
amount: totalPrice,
|
||
address: address,
|
||
items: items.map((item) => ({
|
||
id: item.id,
|
||
title: item.title,
|
||
price: item.price,
|
||
quantity: item.quantity,
|
||
})),
|
||
}),
|
||
})
|
||
|
||
if (!response.ok) {
|
||
throw new Error("Ошибка при создании платежа")
|
||
}
|
||
|
||
const data = await response.json()
|
||
if (!data.paymentUrl) {
|
||
throw new Error("Не получена ссылка на оплату")
|
||
}
|
||
|
||
setPaymentLink(data.paymentUrl)
|
||
setStep(2)
|
||
} catch (error) {
|
||
console.error("Error generating payment link:", error)
|
||
setError("Не удалось создать ссылку для оплаты. Пожалуйста, попробуйте еще раз.")
|
||
} finally {
|
||
setIsProcessing(false)
|
||
}
|
||
}
|
||
|
||
const handlePaymentConfirmation = async () => {
|
||
setIsProcessing(true)
|
||
setError(null)
|
||
try {
|
||
// Here you would typically check the payment status with your backend
|
||
clearCart()
|
||
setIsOrderPlaced(true)
|
||
} catch (error) {
|
||
console.error("Error verifying payment:", error)
|
||
setError("Не удалось проверить статус оплаты. Пожалуйста, попробуйте еще раз.")
|
||
} finally {
|
||
setIsProcessing(false)
|
||
}
|
||
}
|
||
|
||
if (getTotalItems() === 0) {
|
||
return (
|
||
<div className="text-center py-10">
|
||
<p className="text-xl">Ваша корзина пуста. Добавьте товары перед оформлением заказа.</p>
|
||
<Button onClick={() => router.push("/")} className="mt-4">
|
||
Вернуться к покупкам
|
||
</Button>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
if (isOrderPlaced) {
|
||
return (
|
||
<div className="text-center py-10">
|
||
<CheckCircle2 className="w-16 h-16 text-green-500 mx-auto mb-4" />
|
||
<h2 className="text-2xl font-bold mb-2">Заказ успешно оформлен!</h2>
|
||
<p className="mb-4">Спасибо за покупку. Ваш заказ будет доставлен по указанному адресу.</p>
|
||
<Button onClick={() => router.push("/")}>Вернуться на главную</Button>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<div className="space-y-8">
|
||
{error && <div className="bg-red-50 border border-red-200 text-red-600 px-4 py-3 rounded">{error}</div>}
|
||
|
||
{step === 0 && (
|
||
<form onSubmit={handleAddressSubmit} className="space-y-4">
|
||
<h2 className="text-xl font-bold mb-4">Адрес доставки</h2>
|
||
<div>
|
||
<Label htmlFor="address">Адрес</Label>
|
||
<Textarea
|
||
id="address"
|
||
value={address}
|
||
onChange={(e) => setAddress(e.target.value)}
|
||
placeholder="Введите полный адрес доставки"
|
||
required
|
||
/>
|
||
</div>
|
||
<Button type="submit" className="w-full">
|
||
Продолжить
|
||
</Button>
|
||
</form>
|
||
)}
|
||
|
||
{step === 1 && (
|
||
<div className="space-y-4">
|
||
<h2 className="text-xl font-bold mb-4">Оплата</h2>
|
||
<div className="bg-gray-100 p-4 rounded-md">
|
||
<h3 className="font-semibold mb-2">Итого к оплате:</h3>
|
||
<p className="text-2xl font-bold">{totalPrice} ₽</p>
|
||
</div>
|
||
<Button onClick={handleInitiatePayment} disabled={isProcessing} className="w-full">
|
||
{isProcessing ? "Создание ссылки..." : "Перейти к оплате"}
|
||
</Button>
|
||
</div>
|
||
)}
|
||
|
||
{step === 2 && (
|
||
<div className="space-y-4">
|
||
<h2 className="text-xl font-bold mb-4">Завершение оплаты</h2>
|
||
<p>Пожалуйста, перейдите по ссылке ниже для оплаты:</p>
|
||
<a
|
||
href={paymentLink}
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
className="text-blue-600 hover:underline flex items-center"
|
||
>
|
||
Оплатить заказ <ExternalLink className="ml-1 w-4 h-4" />
|
||
</a>
|
||
<Button onClick={handlePaymentConfirmation} disabled={isProcessing} className="w-full">
|
||
{isProcessing ? "Проверка оплаты..." : "Я оплатил"}
|
||
</Button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
)
|
||
}
|
||
|