Refactor embed handling and enhance user experience across components

- Integrated the new `buildEmbedFromPayload` function in Scheduler, Tags, and Welcome components to streamline embed creation and management.
- Updated validation schemas to require embed content checks, ensuring robust data integrity for embeds.
- Enhanced localization files to include new placeholder descriptions and improve user guidance for embed fields.
- Refactored embed parsing logic to utilize the `WelcomeEmbedSchema`, improving consistency and validation across the application.
This commit is contained in:
TheOnlyMace
2026-07-22 22:30:46 +02:00
parent e7a3162494
commit 95eed45ec4
19 changed files with 500 additions and 146 deletions

View File

@@ -1,6 +1,6 @@
'use client';
import type { ScheduledMessageDashboard, WelcomeEmbed } from '@nexumi/shared';
import { embedHasContent, type ScheduledMessageDashboard, type WelcomeEmbed } from '@nexumi/shared';
import { Plus, Trash2 } from 'lucide-react';
import { useState } from 'react';
import { toast } from 'sonner';
@@ -48,6 +48,12 @@ function schedulePreview(schedule: ScheduledMessageDashboard, t: (key: string) =
if (schedule.embed?.description?.trim()) {
return schedule.embed.description;
}
if (schedule.embed?.authorName?.trim()) {
return schedule.embed.authorName;
}
if (schedule.embed?.footerText?.trim()) {
return schedule.embed.footerText;
}
return t('modulePages.scheduler.noContent');
}
@@ -64,7 +70,8 @@ export function SchedulerManager({ guildId, initialSchedules }: SchedulerManager
async function handleCreate() {
const embed = normalizeEmbed(draft.embed);
const hasContent = Boolean(draft.content.trim()) || Boolean(embed?.title) || Boolean(embed?.description);
const hasContent =
Boolean(draft.content.trim()) || embedHasContent(embed) || embed?.color !== undefined;
if (!draft.channelId.trim() || !hasContent || (!draft.cron.trim() && !draft.runAt)) {
toast.error(t('modulePages.scheduler.formIncomplete'));
return;

View File

@@ -1,6 +1,6 @@
'use client';
import type { TagDashboard, TagResponseType, WelcomeEmbed } from '@nexumi/shared';
import { embedHasContent, type TagDashboard, type TagResponseType, type WelcomeEmbed } from '@nexumi/shared';
import { Plus, Trash2 } from 'lucide-react';
import { useState } from 'react';
import { toast } from 'sonner';
@@ -57,7 +57,7 @@ export function TagsManager({ guildId, initialTags }: TagsManagerProps) {
return;
}
const embed = draft.responseType === 'EMBED' ? normalizeEmbed(draft.embed) : null;
if (draft.responseType === 'EMBED' && !embed?.title && !embed?.description) {
if (draft.responseType === 'EMBED' && !embedHasContent(embed) && embed?.color === undefined) {
toast.error(t('modulePages.tags.embedRequired'));
return;
}
@@ -99,7 +99,7 @@ export function TagsManager({ guildId, initialTags }: TagsManagerProps) {
async function handleSave(tag: LocalTag) {
const embed = tag.responseType === 'EMBED' ? normalizeEmbed(tag.embed ?? null) : null;
if (tag.responseType === 'EMBED' && !embed?.title && !embed?.description) {
if (tag.responseType === 'EMBED' && !embedHasContent(embed) && embed?.color === undefined) {
toast.error(t('modulePages.tags.embedRequired'));
return;
}

View File

@@ -25,7 +25,9 @@ const WELCOME_PREVIEW_VARS = {
'user.name': 'Alex',
'user.tag': 'Alex',
'user.id': '123456789012345678',
'user.avatar': 'https://cdn.discordapp.com/embed/avatars/0.png',
server: 'Nexumi',
'server.icon': 'https://cdn.discordapp.com/embed/avatars/1.png',
memberCount: '128'
};