fix: resolve build-time type error in dashboard pages by relaxing submitAction return type

- Update PublicationLayoutProps and PublicationDrawerProps to allow 'void' as a valid return type for server actions (supporting redirects).
- Improve error handling in PublicationLayout and PublicationDrawer to safely process both object and void responses.
- Update EditEntityPage to include missing user authentication and use specialized PublicationLayout for 'posts' entity.
This commit is contained in:
Carlos (Almeira) 2026-03-28 10:03:54 -05:00
parent 339ac0125e
commit 956360a693
4 changed files with 37 additions and 9 deletions

View File

@ -1,10 +1,11 @@
import { APPWRITE_ALMEIRA_CONFIG, projectId, endpoint } from '@/lib/appwrite'; import { APPWRITE_ALMEIRA_CONFIG, projectId, endpoint } from '@/lib/appwrite';
import { createSessionClient } from '@/lib/appwrite.server'; import { createSessionClient, getLoggedInUser } from '@/lib/appwrite.server';
import { collectionMap, SCHEMA_MAP } from '@/lib/schema'; import { collectionMap, SCHEMA_MAP } from '@/lib/schema';
import { updateDocumentServer } from '@/app/actions/appwrite'; import { updateDocumentServer } from '@/app/actions/appwrite';
import { updateEntityAction } from '@/app/actions/entities'; import { updateEntityAction } from '@/app/actions/entities';
import { redirect } from 'next/navigation'; import { redirect } from 'next/navigation';
import { EntityForm } from '@/components/dashboard/EntityForm'; import { EntityForm } from '@/components/dashboard/EntityForm';
import type { AuthUser, Post } from '@/types/publications';
export default async function EditEntityPage({ params }: { params: Promise<{ entity: string, id: string }> }) { export default async function EditEntityPage({ params }: { params: Promise<{ entity: string, id: string }> }) {
const { entity, id } = await params; const { entity, id } = await params;
@ -26,8 +27,9 @@ export default async function EditEntityPage({ params }: { params: Promise<{ ent
} }
const sessionClient = await createSessionClient(); const sessionClient = await createSessionClient();
if (!sessionClient) { const user = await getLoggedInUser();
throw new Error("No sesión activa"); if (!sessionClient || !user) {
redirect('/login');
} }
// Fetch the existing document // Fetch the existing document
@ -60,7 +62,28 @@ export default async function EditEntityPage({ params }: { params: Promise<{ ent
); );
const boundUpdate = updateEntityAction.bind(null, entity, id); const boundUpdate = updateEntityAction.bind(null, entity, id);
const appwriteConfig = {
endpoint,
projectId,
databaseId: APPWRITE_ALMEIRA_CONFIG.databaseId,
};
// ── POSTS: Use the new PublicationLayout ──────────────
if (entity === 'posts') {
const { default: PublicationLayout } = await import('@/components/publications/PublicationLayout');
return (
<PublicationLayout
initialData={document as Post}
user={user as unknown as AuthUser}
relationData={relationData}
submitAction={boundUpdate}
appwriteConfig={appwriteConfig}
/>
);
}
// ── OTHER ENTITIES: Use the generic EntityForm ────────
return ( return (
<EntityForm <EntityForm
entity={entity} entity={entity}

View File

@ -17,7 +17,7 @@ export interface PublicationDrawerProps {
post: Post | null; post: Post | null;
user: AuthUser; user: AuthUser;
relationData: Record<string, Array<{ $id: string; [key: string]: unknown }>>; relationData: Record<string, Array<{ $id: string; [key: string]: unknown }>>;
submitAction: (formData: FormData) => Promise<{ success: boolean; error?: string; data?: unknown }>; submitAction: (formData: FormData) => Promise<{ success: boolean; error?: string; data?: unknown } | void>;
appwriteConfig: { appwriteConfig: {
endpoint: string; endpoint: string;
projectId: string; projectId: string;
@ -65,7 +65,7 @@ export const PublicationDrawer: React.FC<PublicationDrawerProps> = ({
const wrappedSubmit = useCallback(async (formData: FormData) => { const wrappedSubmit = useCallback(async (formData: FormData) => {
const result = await submitAction(formData); const result = await submitAction(formData);
if (result?.success) { if (!result || result.success) {
onSuccess?.(); onSuccess?.();
} }
return result; return result;

View File

@ -135,11 +135,15 @@ export const PublicationLayout: React.FC<PublicationLayoutProps> = ({
startTransition(async () => { startTransition(async () => {
try { try {
const result = await submitAction(formData); const result = await submitAction(formData);
if (result?.success) { // If result is undefined/void, it likely redirected (success)
if (!result || result.success) {
setOptimisticState('saved'); setOptimisticState('saved');
setTimeout(() => router.push('/dashboard/posts'), 800); // Only redirect manually if we didn't already redirect from the action
if (result) {
setTimeout(() => router.push('/dashboard/posts'), 800);
}
} else { } else {
setOptimisticState('error', result?.error || 'Error al guardar.'); setOptimisticState('error', result.error || 'Error al guardar.');
} }
} catch (err: unknown) { } catch (err: unknown) {
setOptimisticState('error', err instanceof Error ? err.message : 'Error desconocido.'); setOptimisticState('error', err instanceof Error ? err.message : 'Error desconocido.');

View File

@ -149,7 +149,8 @@ export interface PublicationLayoutProps {
/** Datos de relaciones pre-cargados desde el servidor */ /** Datos de relaciones pre-cargados desde el servidor */
relationData: Record<string, Array<{ $id: string; [key: string]: unknown }>>; relationData: Record<string, Array<{ $id: string; [key: string]: unknown }>>;
/** Acción de servidor para guardar */ /** Acción de servidor para guardar */
submitAction: (formData: FormData) => Promise<{ success: boolean; error?: string; data?: unknown }>; /** Acción de servidor para guardar. Puede retornar un objeto de éxito o void (si redirige) */
submitAction: (formData: FormData) => Promise<{ success: boolean; error?: string; data?: unknown } | void>;
/** Usuario autenticado */ /** Usuario autenticado */
user: AuthUser; user: AuthUser;
/** Config de Appwrite para URLs de media */ /** Config de Appwrite para URLs de media */