import { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Separator } from "@/components/ui/separator"; import { aethexToast } from "@/lib/aethex-toast"; import ArmPostCard, { ArmType } from "@/components/feed/ArmPostCard"; import { Loader2, X, Tag } from "lucide-react"; const API_BASE = import.meta.env.VITE_API_BASE || ""; const ARM_OPTIONS: { id: ArmType; label: string }[] = [ { id: "labs", label: "Labs" }, { id: "gameforge", label: "GameForge" }, { id: "corp", label: "Corp" }, { id: "foundation", label: "Foundation" }, { id: "devlink", label: "Dev-Link" }, { id: "nexus", label: "Nexus" }, { id: "staff", label: "Staff" }, ]; const CATEGORIES = [ "Announcement", "Tutorial", "Update", "Question", "Discussion", "Showcase", "Resource", "Other", ]; interface Post { id?: string; title: string; content: string; arm_affiliation: ArmType; tags?: string[]; category?: string; user_profiles?: { id: string; username?: string; full_name?: string; avatar_url?: string; }; created_at?: string; } interface PostComposerProps { open: boolean; onOpenChange: (open: boolean) => void; currentUserId?: string; currentUserProfile?: { id: string; username?: string; full_name?: string; avatar_url?: string; }; editingPost?: Post; onSuccess?: () => void; } export default function PostComposer({ open, onOpenChange, currentUserId, currentUserProfile, editingPost, onSuccess, }: PostComposerProps) { const [title, setTitle] = useState(""); const [content, setContent] = useState(""); const [armAffiliation, setArmAffiliation] = useState("labs"); const [category, setCategory] = useState(""); const [tagInput, setTagInput] = useState(""); const [tags, setTags] = useState([]); const [isSubmitting, setIsSubmitting] = useState(false); // Initialize form with editing post data useEffect(() => { if (editingPost) { setTitle(editingPost.title); setContent(editingPost.content); setArmAffiliation(editingPost.arm_affiliation); setCategory(editingPost.category || ""); setTags(editingPost.tags || []); } else { resetForm(); } }, [editingPost, open]); const resetForm = () => { setTitle(""); setContent(""); setArmAffiliation("labs"); setCategory(""); setTagInput(""); setTags([]); }; const handleAddTag = (e: React.KeyboardEvent) => { if (e.key === "Enter" || e.key === ",") { e.preventDefault(); const trimmedTag = tagInput.trim().toLowerCase(); if (trimmedTag && !tags.includes(trimmedTag) && tags.length < 5) { setTags([...tags, trimmedTag]); setTagInput(""); } } }; const handleRemoveTag = (tagToRemove: string) => { setTags(tags.filter((tag) => tag !== tagToRemove)); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!currentUserId) { aethexToast.error({ title: "Not authenticated", description: "Please log in to create posts", }); return; } if (!title.trim()) { aethexToast.error({ title: "Empty title", description: "Please enter a title", }); return; } if (!content.trim()) { aethexToast.error({ title: "Empty content", description: "Please write some content", }); return; } setIsSubmitting(true); try { const url = `${API_BASE}/api/posts`; const method = editingPost ? "PUT" : "POST"; const payload = { ...(editingPost && { id: editingPost.id }), title: title.trim(), content: content.trim(), arm_affiliation: armAffiliation, author_id: currentUserId, category: category || null, tags: tags, ...(editingPost && { user_id: currentUserId }), }; const response = await fetch(url, { method, headers: { "Content-Type": "application/json", }, body: JSON.stringify(payload), }); if (response.ok) { const data = await response.json(); // Send to Discord if it's a new post if (!editingPost && data.post?.id) { try { await fetch(`${API_BASE}/api/discord/send-community-post`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ post_id: data.post.id, title: title.trim(), content: content.trim(), arm_affiliation: armAffiliation, author_id: currentUserId, tags: tags, category: category || null, }), }).catch((error) => { console.error("Error sending to Discord:", error); // Don't fail the post creation if Discord sends fails }); } catch (error) { console.error("Error calling Discord endpoint:", error); } } aethexToast.success({ title: editingPost ? "Post updated" : "Post created", description: editingPost ? "Your post has been updated" : "Your post has been published to the community feed", }); resetForm(); onOpenChange(false); onSuccess?.(); } else { const error = await response.json(); aethexToast.error({ title: editingPost ? "Failed to update post" : "Failed to create post", description: error.error || "Please try again", }); } } catch (error) { console.error("Error submitting post:", error); aethexToast.error({ title: editingPost ? "Failed to update post" : "Failed to create post", description: "An unexpected error occurred", }); } finally { setIsSubmitting(false); } }; const previewPost: Post = { title: title || "Untitled Post", content: content || "Start typing your post content...", arm_affiliation: armAffiliation, tags, category: category || undefined, user_profiles: currentUserProfile, created_at: new Date().toISOString(), }; return ( {editingPost ? "Edit Post" : "Create a Community Post"}
{/* Form Section */}
{/* Title */}
setTitle(e.target.value)} maxLength={500} disabled={isSubmitting} className="text-base" />

{title.length}/500

{/* Content */}