/** * Edit Projects Page * Cleaned up version with consolidated useEffect hooks * Note: Preserves special logo loading logic for logo_url, favicon_url, og_image_url fields */ import { mdiChartTimelineVariant } from '@mdi/js'; import axios from 'axios'; import Head from 'next/head'; import React, { ReactElement, useEffect, useState } from 'react'; import CardBox from '../../components/CardBox'; import LayoutAuthenticated from '../../layouts/Authenticated'; import SectionMain from '../../components/SectionMain'; import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'; import { getPageTitle } from '../../config'; import { Field, Form, Formik } from 'formik'; import FormField from '../../components/FormField'; import BaseDivider from '../../components/BaseDivider'; import BaseButtons from '../../components/BaseButtons'; import BaseButton from '../../components/BaseButton'; import { deleteItem, update, fetch } from '../../stores/projects/projectsSlice'; import { useAppDispatch, useAppSelector } from '../../stores/hooks'; import { useRouter } from 'next/router'; import type { Project } from '../../types/entities'; import { logger } from '../../lib/logger'; const initVals = { name: '', slug: '', description: '', logo_url: '', favicon_url: '', og_image_url: '', is_deleted: false, deleted_at_time: new Date(), }; const EditProjectsPage = () => { const router = useRouter(); const dispatch = useAppDispatch(); const [initialValues, setInitialValues] = useState(initVals); const [logoAssets, setLogoAssets] = useState< { id: string; cdn_url: string; storage_key?: string; name: string }[] >([]); const [isLoadingLogoAssets, setIsLoadingLogoAssets] = useState(false); const projectsState = useAppSelector((state) => state.projects); const projects = projectsState.projects as Project | Project[] | undefined; const project = Array.isArray(projects) ? projects[0] : projects; const { id } = router.query as { id?: string }; // Fetch entity data useEffect(() => { if (id) { dispatch(fetch({ id: id as string })); } }, [id, dispatch]); // Load logo assets for the project const loadLogoAssets = async (projectId: string) => { if (!projectId) { setLogoAssets([]); return; } setIsLoadingLogoAssets(true); try { const response = await axios.get( `/assets?limit=500&page=0&sort=desc&field=createdAt&projectId=${projectId}`, ); const rows = Array.isArray(response?.data?.rows) ? response.data.rows : []; const taggedLogoAssets = rows.filter( (asset: { cdn_url?: string; asset_type?: string; type?: string; name?: string; }) => typeof asset?.cdn_url === 'string' && asset.cdn_url && asset?.asset_type === 'image' && (asset?.type === 'logo' || (typeof asset?.name === 'string' && asset.name.startsWith('[LOGO] '))), ); setLogoAssets(taggedLogoAssets); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error( 'Failed to load logo assets for project edit:', error instanceof Error ? error : { error: errorMessage }, ); setLogoAssets([]); } finally { setIsLoadingLogoAssets(false); } }; useEffect(() => { setLogoAssets([]); setIsLoadingLogoAssets(true); if (typeof id === 'string' && id) { void loadLogoAssets(id); } else { setIsLoadingLogoAssets(false); } }, [id]); // Sync form values with fetched data (consolidated from redundant useEffects) useEffect(() => { if (typeof project === 'object' && project !== null) { const projectData = project as unknown as Record; setInitialValues({ name: String(projectData.name || ''), slug: String(projectData.slug || ''), description: String(projectData.description || ''), logo_url: String(projectData.logo_url || ''), favicon_url: String(projectData.favicon_url || ''), og_image_url: String(projectData.og_image_url || ''), is_deleted: Boolean(projectData.is_deleted), deleted_at_time: projectData.deleted_at_time ? new Date(projectData.deleted_at_time as string) : new Date(), }); } }, [project]); const handleSubmit = async (data: typeof initVals) => { const apiData: Partial = { name: data.name, slug: data.slug, description: data.description, logo_url: data.logo_url, favicon_url: data.favicon_url, og_image_url: data.og_image_url, }; await dispatch(update({ id: id as string, data: apiData })); await router.push('/projects/projects-list'); }; const handleDelete = async () => { const projectId = typeof id === 'string' ? id : null; if (!projectId) { return; } if (!window.confirm('Are you sure you want to delete this project?')) { return; } await dispatch(deleteItem(projectId)); await router.push('/projects/projects-list'); }; return ( <> {getPageTitle('Edit projects')} {''} handleSubmit(values)} > {({ values }) => (
{logoAssets.map((asset) => ( ))} {values.logo_url && !logoAssets.some( (asset) => (asset.storage_key || asset.cdn_url) === values.logo_url, ) && ( )} {values.logo_url && ( Preview selected logo )} {logoAssets.map((asset) => ( ))} {values.favicon_url && !logoAssets.some( (asset) => (asset.storage_key || asset.cdn_url) === values.favicon_url, ) && ( )} {values.favicon_url && ( Preview selected favicon )} {logoAssets.map((asset) => ( ))} {values.og_image_url && !logoAssets.some( (asset) => (asset.storage_key || asset.cdn_url) === values.og_image_url, ) && ( )} {values.og_image_url && ( Preview selected OG image )} router.push('/projects/projects-list')} /> )}
); }; EditProjectsPage.getLayout = function getLayout(page: ReactElement) { return ( {page} ); }; export default EditProjectsPage;