217 lines
6.4 KiB
JavaScript
217 lines
6.4 KiB
JavaScript
"use client";
|
|
|
|
import React, { useState, useEffect, Suspense } from "react";
|
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
|
|
function AddressContent() {
|
|
const router = useRouter();
|
|
const searchParams = useSearchParams();
|
|
const [addresses, setAddresses] = useState([]);
|
|
const [showForm, setShowForm] = useState(false);
|
|
const [formData, setFormData] = useState({
|
|
name: "",
|
|
phone: "",
|
|
address: "",
|
|
isDefault: false,
|
|
});
|
|
|
|
useEffect(() => {
|
|
const token = localStorage.getItem("token");
|
|
if (!token) {
|
|
router.push("/login");
|
|
return;
|
|
}
|
|
fetchAddresses();
|
|
}, [router]);
|
|
|
|
const fetchAddresses = async () => {
|
|
try {
|
|
const res = await fetch("/api/address", {
|
|
headers: {
|
|
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
|
},
|
|
});
|
|
const data = await res.json();
|
|
setAddresses(data);
|
|
} catch (error) {
|
|
console.error("获取地址失败:", error);
|
|
}
|
|
};
|
|
|
|
const handleSelectAddress = (address) => {
|
|
const returnUrl = searchParams.get("returnUrl");
|
|
const items = searchParams.get("items");
|
|
const products = searchParams.get("products");
|
|
const quantity = searchParams.get("quantity");
|
|
|
|
localStorage.setItem("selectedAddress", JSON.stringify(address));
|
|
|
|
if (returnUrl) {
|
|
let finalUrl = returnUrl;
|
|
if (items) {
|
|
finalUrl += `?items=${items}`;
|
|
} else if (products && quantity) {
|
|
finalUrl += `?products=${products}&quantity=${quantity}`;
|
|
}
|
|
router.replace(finalUrl);
|
|
} else {
|
|
router.replace("/checkout");
|
|
}
|
|
};
|
|
|
|
const handleSubmit = async (e) => {
|
|
e.preventDefault();
|
|
try {
|
|
const res = await fetch("/api/address", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
|
},
|
|
body: JSON.stringify(formData),
|
|
});
|
|
|
|
if (!res.ok) {
|
|
throw new Error("添加地址失败");
|
|
}
|
|
|
|
setShowForm(false);
|
|
setFormData({ name: "", phone: "", address: "", isDefault: false });
|
|
await fetchAddresses();
|
|
} catch (error) {
|
|
console.error("添加地址失败:", error);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gray-50 p-4">
|
|
<div className="max-w-md mx-auto">
|
|
<h1 className="text-xl font-bold mb-4">收货地址</h1>
|
|
|
|
{/* 地址列表 */}
|
|
<div className="space-y-4 mb-6">
|
|
{addresses.map((address) => (
|
|
<div
|
|
key={address._id}
|
|
className="bg-white p-4 rounded-lg shadow-sm"
|
|
onClick={() => handleSelectAddress(address)}
|
|
>
|
|
<div className="flex justify-between items-center mb-2">
|
|
<span className="font-medium">{address.name}</span>
|
|
<span>{address.phone}</span>
|
|
</div>
|
|
<p className="text-gray-600 text-sm">{address.address}</p>
|
|
{address.isDefault && (
|
|
<span className="mt-2 inline-block px-2 py-1 text-xs text-yellow-600 border border-yellow-600 rounded">
|
|
默认地址
|
|
</span>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* 添加地址按钮 */}
|
|
{!showForm && (
|
|
<button
|
|
onClick={() => setShowForm(true)}
|
|
className="w-full bg-yellow-400 text-white py-3 rounded-lg"
|
|
>
|
|
添加新地址
|
|
</button>
|
|
)}
|
|
|
|
{/* 添加地址表单 */}
|
|
{showForm && (
|
|
<form onSubmit={handleSubmit} className="bg-white p-4 rounded-lg">
|
|
<div className="space-y-4">
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|
联系人
|
|
</label>
|
|
<input
|
|
type="text"
|
|
required
|
|
className="w-full px-3 py-2 border rounded-lg"
|
|
value={formData.name}
|
|
onChange={(e) =>
|
|
setFormData({ ...formData, name: e.target.value })
|
|
}
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|
手机号
|
|
</label>
|
|
<input
|
|
type="tel"
|
|
required
|
|
className="w-full px-3 py-2 border rounded-lg"
|
|
value={formData.phone}
|
|
onChange={(e) =>
|
|
setFormData({ ...formData, phone: e.target.value })
|
|
}
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|
详细地址
|
|
</label>
|
|
<textarea
|
|
required
|
|
className="w-full px-3 py-2 border rounded-lg"
|
|
rows="3"
|
|
value={formData.address}
|
|
onChange={(e) =>
|
|
setFormData({ ...formData, address: e.target.value })
|
|
}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex items-center">
|
|
<input
|
|
type="checkbox"
|
|
id="isDefault"
|
|
checked={formData.isDefault}
|
|
onChange={(e) =>
|
|
setFormData({ ...formData, isDefault: e.target.checked })
|
|
}
|
|
className="mr-2"
|
|
/>
|
|
<label htmlFor="isDefault" className="text-sm text-gray-700">
|
|
设为默认地址
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-6 flex gap-4">
|
|
<button
|
|
type="button"
|
|
onClick={() => setShowForm(false)}
|
|
className="flex-1 py-2 border border-gray-300 rounded-lg"
|
|
>
|
|
取消
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
className="flex-1 bg-yellow-400 text-white py-2 rounded-lg"
|
|
>
|
|
保存
|
|
</button>
|
|
</div>
|
|
</form>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function AddressPage() {
|
|
return (
|
|
<Suspense fallback={<div className="p-4">加载中...</div>}>
|
|
<AddressContent />
|
|
</Suspense>
|
|
);
|
|
}
|