ghostguild-org/app/components/UpdateForm.vue

184 lines
4.6 KiB
Vue

<template>
<div class="space-y-6">
<UFormField label="What's on your mind?" name="content" required>
<UTextarea
v-model="formData.content"
placeholder="Share your thoughts, updates, questions, or learnings with the community..."
:rows="8"
autoresize
:maxrows="20"
/>
</UFormField>
<!-- Privacy Settings -->
<div class="border border-ghost-700 rounded-lg p-4 bg-ghost-800/30">
<h3 class="text-sm font-medium text-ghost-200 mb-4">Privacy Settings</h3>
<div class="space-y-3">
<label class="flex items-center gap-3 cursor-pointer">
<input
v-model="formData.privacy"
type="radio"
value="public"
class="w-4 h-4 text-ghost-400"
/>
<div>
<div class="text-ghost-200 font-medium">Public</div>
<div class="text-sm text-ghost-400">
Visible to everyone, including non-members
</div>
</div>
</label>
<label class="flex items-center gap-3 cursor-pointer">
<input
v-model="formData.privacy"
type="radio"
value="members"
class="w-4 h-4 text-ghost-400"
/>
<div>
<div class="text-ghost-200 font-medium">Members Only</div>
<div class="text-sm text-ghost-400">
Only visible to Ghost Guild members
</div>
</div>
</label>
<label class="flex items-center gap-3 cursor-pointer">
<input
v-model="formData.privacy"
type="radio"
value="private"
class="w-4 h-4 text-ghost-400"
/>
<div>
<div class="text-ghost-200 font-medium">Private</div>
<div class="text-sm text-ghost-400">Only visible to you</div>
</div>
</label>
</div>
</div>
<!-- Image Upload (Future) -->
<!-- TODO: Add image upload integration with Cloudinary -->
<!-- Comments Toggle -->
<div class="flex items-center gap-3">
<USwitch v-model="formData.commentsEnabled" />
<div>
<div class="text-ghost-200 font-medium">Enable Comments</div>
<div class="text-sm text-ghost-400">
Allow members to comment on this update
</div>
</div>
</div>
<!-- Actions -->
<div
class="flex justify-between items-center pt-4 border-t border-ghost-700"
>
<UButton variant="ghost" color="neutral" @click="$emit('cancel')">
Cancel
</UButton>
<UButton
:loading="submitting"
:disabled="!formData.content.trim()"
@click="handleSubmit"
>
{{ submitLabel }}
</UButton>
</div>
<!-- Error Message -->
<div
v-if="error"
class="bg-red-500/10 border border-red-500/30 rounded-lg p-4"
>
<p class="text-red-300">{{ error }}</p>
</div>
</div>
</template>
<script setup>
const props = defineProps({
initialData: {
type: Object,
default: () => ({
content: "",
privacy: "members",
commentsEnabled: true,
images: [],
}),
},
submitLabel: {
type: String,
default: "Post Update",
},
submitting: {
type: Boolean,
default: false,
},
error: {
type: String,
default: null,
},
});
const emit = defineEmits(["submit", "cancel"]);
const formData = reactive({
content: props.initialData.content || "",
privacy: props.initialData.privacy || "members",
commentsEnabled: props.initialData.commentsEnabled ?? true,
images: props.initialData.images || [],
});
const handleSubmit = () => {
if (!formData.content.trim()) return;
emit("submit", { ...formData });
};
// Watch for initialData changes (for edit mode)
watch(
() => props.initialData,
(newData) => {
if (newData) {
formData.content = newData.content || "";
formData.privacy = newData.privacy || "members";
formData.commentsEnabled = newData.commentsEnabled ?? true;
formData.images = newData.images || [];
}
},
{ immediate: true },
);
</script>
<style scoped>
/* Field labels */
:deep(label) {
color: rgb(231 229 228) !important;
font-weight: 500;
}
/* Textarea styling */
:deep(textarea) {
background-color: rgb(41 37 36) !important;
color: rgb(231 229 228) !important;
border-color: rgb(87 83 78) !important;
}
:deep(textarea::placeholder) {
color: rgb(120 113 108) !important;
}
:deep(textarea:focus) {
border-color: rgb(168 162 158) !important;
background-color: rgb(44 40 39) !important;
}
/* Radio buttons */
input[type="radio"] {
accent-color: rgb(168 162 158);
}
</style>