Initial Mebbling hub implementation
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
"use client";
|
||||
|
||||
import { FormEvent, useState } from "react";
|
||||
|
||||
type Source = { id: number; name: string };
|
||||
|
||||
export function PublishForm({ sources }: { sources: Source[] }) {
|
||||
const [error, setError] = useState("");
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
async function submit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault();
|
||||
setSubmitting(true); setError("");
|
||||
try {
|
||||
const response = await fetch("/api/posts", { method: "POST", body: new FormData(event.currentTarget), headers: { Accept: "application/json" } });
|
||||
const result = await response.json();
|
||||
if (!response.ok) throw new Error(result.error || "發佈失敗");
|
||||
window.location.assign(`/posts/${result.id}`);
|
||||
} catch (reason) {
|
||||
setError(reason instanceof Error ? reason.message : "發佈失敗");
|
||||
setSubmitting(false);
|
||||
}
|
||||
}
|
||||
|
||||
return <form onSubmit={submit} encType="multipart/form-data">
|
||||
<label>內容(Markdown)<textarea name="content" required /></label>
|
||||
<label>標籤(逗號分隔)<input name="tags" placeholder="旅行, 想法" /></label>
|
||||
<label>可見性<select name="visibility" defaultValue="PUBLIC"><option value="PUBLIC">公開</option><option value="PROTECTED">受保護</option><option value="PRIVATE">私人</option></select></label>
|
||||
<label>發佈來源<select name="sourceId" required>{sources.map((source) => <option key={source.id} value={source.id}>{source.name}</option>)}</select></label>
|
||||
<label>圖片或附件(每檔最多 10 MB)<input name="attachments" type="file" multiple /></label>
|
||||
{error && <p className="error">{error}</p>}
|
||||
<button disabled={submitting}>{submitting ? "發佈中…" : "發佈並同步"}</button>
|
||||
</form>;
|
||||
}
|
||||
Reference in New Issue
Block a user