aa
This commit is contained in:
@@ -5,6 +5,13 @@ import { CATEGORIES } from "@/lib/ui-config";
|
||||
import type { CategoryId, Place } from "@/lib/types";
|
||||
import type { Dispatch } from "@/lib/app-state";
|
||||
import { FieldLabel } from "@/components/ui-primitives";
|
||||
import {
|
||||
CoverPicker,
|
||||
commitCover,
|
||||
coverStateFromUrl,
|
||||
disposeCover,
|
||||
type CoverState,
|
||||
} from "@/components/cover-picker";
|
||||
import { Icons } from "@/components/icons";
|
||||
import { editPlace } from "@/lib/db/actions";
|
||||
|
||||
@@ -22,6 +29,7 @@ export function EditPlaceSheet({
|
||||
const [category, setCategory] = useState<CategoryId>(place.category);
|
||||
const [tags, setTags] = useState<string[]>(place.tags);
|
||||
const [tagInput, setTagInput] = useState("");
|
||||
const [cover, setCover] = useState<CoverState>(() => coverStateFromUrl(place.cover_url));
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [, startTransition] = useTransition();
|
||||
|
||||
@@ -37,24 +45,32 @@ export function EditPlaceSheet({
|
||||
if (!isValid) return;
|
||||
setSaving(true);
|
||||
const trimmedAddress = address.trim();
|
||||
startTransition(() => {
|
||||
editPlace(place.id, {
|
||||
name: name.trim(),
|
||||
address: trimmedAddress,
|
||||
short_address: trimmedAddress.split(",").slice(0, 2).join(" · "),
|
||||
city: trimmedAddress.split(",").pop()?.trim() || "",
|
||||
category,
|
||||
tags,
|
||||
cover_url: place.cover_url ?? null,
|
||||
})
|
||||
.then(() => {
|
||||
onClose();
|
||||
dispatch({ type: "TOAST", value: "Đã lưu thay đổi" });
|
||||
})
|
||||
.catch(() => {
|
||||
setSaving(false);
|
||||
dispatch({ type: "TOAST", value: "Lưu thất bại" });
|
||||
startTransition(async () => {
|
||||
try {
|
||||
// Upload to R2 only now — local blob (if any) is converted to a real
|
||||
// URL. An existing URL is returned unchanged.
|
||||
const coverUrl = await commitCover(cover);
|
||||
const patch = {
|
||||
name: name.trim(),
|
||||
address: trimmedAddress,
|
||||
short_address: trimmedAddress.split(",").slice(0, 2).join(" · "),
|
||||
city: trimmedAddress.split(",").pop()?.trim() || "",
|
||||
category,
|
||||
tags,
|
||||
cover_url: coverUrl,
|
||||
};
|
||||
await editPlace(place.id, patch);
|
||||
disposeCover(cover);
|
||||
dispatch({ type: "PATCH_PLACE", placeId: place.id, patch });
|
||||
onClose();
|
||||
dispatch({ type: "TOAST", value: "Đã lưu thay đổi" });
|
||||
} catch (e) {
|
||||
setSaving(false);
|
||||
dispatch({
|
||||
type: "TOAST",
|
||||
value: (e as Error).message || "Lưu thất bại",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -89,6 +105,14 @@ export function EditPlaceSheet({
|
||||
</div>
|
||||
|
||||
<div style={{ flex: 1, overflowY: "auto", padding: "4px 16px" }}>
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<CoverPicker
|
||||
value={cover}
|
||||
onChange={setCover}
|
||||
onError={(msg) => dispatch({ type: "TOAST", value: msg })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<FieldLabel required>Tên địa điểm</FieldLabel>
|
||||
<div className="input">
|
||||
<input value={name} onChange={(e) => setName(e.target.value)} />
|
||||
|
||||
Reference in New Issue
Block a user