162 lines
6.4 KiB
TypeScript
162 lines
6.4 KiB
TypeScript
"use client"
|
||
|
||
import { useState, useEffect } from "react"
|
||
import { useRouter, useParams } from "next/navigation"
|
||
import { ChevronLeft } from "lucide-react"
|
||
import { useStore } from "@/lib/store"
|
||
|
||
export default function EditAddressPage() {
|
||
const router = useRouter()
|
||
const params = useParams()
|
||
const id = params?.id as string
|
||
const { user } = useStore()
|
||
const [loading, setLoading] = useState(false)
|
||
const [fetching, setFetching] = useState(true)
|
||
const [name, setName] = useState("")
|
||
const [phone, setPhone] = useState("")
|
||
const [province, setProvince] = useState("")
|
||
const [city, setCity] = useState("")
|
||
const [district, setDistrict] = useState("")
|
||
const [detail, setDetail] = useState("")
|
||
const [isDefault, setIsDefault] = useState(false)
|
||
|
||
useEffect(() => {
|
||
if (!id || !user?.id) {
|
||
setFetching(false)
|
||
return
|
||
}
|
||
fetch(`/api/user/addresses/${id}`)
|
||
.then((res) => res.json())
|
||
.then((data) => {
|
||
if (data.success && data.item) {
|
||
const a = data.item
|
||
setName(a.name || "")
|
||
setPhone(a.phone || "")
|
||
setProvince(a.province || "")
|
||
setCity(a.city || "")
|
||
setDistrict(a.district || "")
|
||
setDetail(a.detail || "")
|
||
setIsDefault(!!a.isDefault)
|
||
}
|
||
})
|
||
.finally(() => setFetching(false))
|
||
}, [id, user?.id])
|
||
|
||
if (!user?.id) {
|
||
return (
|
||
<div className="min-h-screen bg-black text-white flex items-center justify-center">
|
||
<p className="text-white/60">请先登录</p>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
const handleSubmit = async (e: React.FormEvent) => {
|
||
e.preventDefault()
|
||
if (!name.trim()) {
|
||
alert("请输入收货人姓名")
|
||
return
|
||
}
|
||
if (!/^1[3-9]\d{9}$/.test(phone)) {
|
||
alert("请输入正确的手机号")
|
||
return
|
||
}
|
||
if (!detail.trim()) {
|
||
alert("请输入详细地址")
|
||
return
|
||
}
|
||
setLoading(true)
|
||
try {
|
||
const res = await fetch(`/api/user/addresses/${id}`, {
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify({
|
||
name: name.trim(),
|
||
phone: phone.trim(),
|
||
province: (province ?? "").trim(),
|
||
city: (city ?? "").trim(),
|
||
district: (district ?? "").trim(),
|
||
detail: detail.trim(),
|
||
isDefault,
|
||
}),
|
||
})
|
||
const data = await res.json()
|
||
if (data.success) {
|
||
router.push("/view/my/addresses")
|
||
} else {
|
||
alert(data.message || "保存失败")
|
||
}
|
||
} catch {
|
||
alert("保存失败")
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
if (fetching) {
|
||
return (
|
||
<div className="min-h-screen bg-black text-white flex items-center justify-center">
|
||
<div className="animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-[#00CED1]" />
|
||
</div>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<div className="min-h-screen bg-black text-white pb-24">
|
||
<header className="sticky top-0 z-40 bg-black/90 backdrop-blur-xl border-b border-white/5">
|
||
<div className="px-4 py-3 flex items-center">
|
||
<button onClick={() => router.back()} className="w-8 h-8 rounded-full bg-white/10 flex items-center justify-center">
|
||
<ChevronLeft className="w-5 h-5 text-white" />
|
||
</button>
|
||
<h1 className="flex-1 text-center text-lg font-semibold text-white">编辑地址</h1>
|
||
<div className="w-8" />
|
||
</div>
|
||
</header>
|
||
|
||
<form onSubmit={handleSubmit} className="px-4 py-4 space-y-4">
|
||
<div className="rounded-2xl bg-[#1c1c1e] border border-white/5 overflow-hidden">
|
||
<div className="flex items-center justify-between p-4 border-b border-white/5">
|
||
<label className="text-white text-sm w-24">收货人</label>
|
||
<input
|
||
type="text"
|
||
value={name}
|
||
onChange={(e) => setName(e.target.value)}
|
||
placeholder="请输入收货人姓名"
|
||
className="flex-1 bg-transparent text-white text-sm text-right placeholder-white/30 outline-none"
|
||
/>
|
||
</div>
|
||
<div className="flex items-center justify-between p-4 border-b border-white/5">
|
||
<label className="text-white text-sm w-24">手机号</label>
|
||
<input
|
||
type="tel"
|
||
maxLength={11}
|
||
value={phone}
|
||
onChange={(e) => setPhone(e.target.value.replace(/\D/g, ""))}
|
||
placeholder="请输入手机号"
|
||
className="flex-1 bg-transparent text-white text-sm text-right placeholder-white/30 outline-none"
|
||
/>
|
||
</div>
|
||
<div className="flex items-center justify-between p-4 border-b border-white/5">
|
||
<label className="text-white text-sm w-24">省市区(选填)</label>
|
||
<div className="flex-1 flex gap-2 justify-end">
|
||
<input type="text" value={province} onChange={(e) => setProvince(e.target.value)} placeholder="省" className="flex-1 max-w-24 bg-transparent text-white text-sm text-right placeholder-white/30 outline-none" />
|
||
<input type="text" value={city} onChange={(e) => setCity(e.target.value)} placeholder="市" className="flex-1 max-w-24 bg-transparent text-white text-sm text-right placeholder-white/30 outline-none" />
|
||
<input type="text" value={district} onChange={(e) => setDistrict(e.target.value)} placeholder="区" className="flex-1 max-w-24 bg-transparent text-white text-sm text-right placeholder-white/30 outline-none" />
|
||
</div>
|
||
</div>
|
||
<div className="flex items-start justify-between p-4">
|
||
<label className="text-white text-sm w-24 pt-2">详细地址</label>
|
||
<textarea value={detail} onChange={(e) => setDetail(e.target.value)} placeholder="街道、楼栋、门牌号等" rows={3} className="flex-1 bg-transparent text-white text-sm text-right placeholder-white/30 outline-none resize-none" />
|
||
</div>
|
||
<div className="flex items-center justify-between p-4 border-t border-white/5">
|
||
<span className="text-white text-sm">设为默认地址</span>
|
||
<input type="checkbox" checked={isDefault} onChange={(e) => setIsDefault(e.target.checked)} className="w-5 h-5 rounded accent-[#00CED1]" />
|
||
</div>
|
||
</div>
|
||
<button type="submit" disabled={loading} className="w-full py-3 rounded-xl bg-[#00CED1] text-black font-medium disabled:opacity-50">
|
||
{loading ? "保存中..." : "保存"}
|
||
</button>
|
||
</form>
|
||
</div>
|
||
)
|
||
}
|