import type { MenuProps } from '@/shared/antd-imports'; import { Empty, List, Menu, Skeleton, Tabs, Tag, Typography, Image, Input, Flex, } from '@/shared/antd-imports'; import React, { useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import { RootState } from '@/app/store'; import { projectTemplatesApiService } from '@/api/project-templates/project-templates.api.service'; import { ICustomTemplate, IProjectTemplate, IWorklenzTemplate, } from '@/types/project-templates/project-templates.types'; import './template-drawer.css'; import { SearchOutlined } from '@/shared/antd-imports'; import logger from '@/utils/errorLogger'; const { Title, Text } = Typography; interface TemplateDrawerProps { showBothTabs: boolean; templateSelected: (templateId: string) => void; selectedTemplateType: (type: 'worklenz' | 'custom') => void; } const TemplateDrawer: React.FC = ({ showBothTabs = false, templateSelected = (templateId: string) => { if (!templateId) return; templateId; }, selectedTemplateType = (type: 'worklenz' | 'custom') => { type; }, }) => { const themeMode = useSelector((state: RootState) => state.themeReducer.mode); const { t } = useTranslation('template-drawer'); const [searchQuery, setSearchQuery] = useState(''); const [templates, setTemplates] = useState([]); const [loadingTemplates, setLoadingTemplates] = useState(false); const [customTemplates, setCustomTemplates] = useState([]); const [loadingCustomTemplates, setLoadingCustomTemplates] = useState(false); const [selectedTemplate, setSelectedTemplate] = useState(null); const [loadingSelectedTemplate, setLoadingSelectedTemplate] = useState(false); const getSelectedTemplate = async (templateId: string) => { try { setLoadingSelectedTemplate(true); const res = await projectTemplatesApiService.getByTemplateId(templateId); if (res.done) { setSelectedTemplate(res.body); } } catch (error) { logger.error('Error loading template:', error); } finally { setLoadingSelectedTemplate(false); } }; const getTemplates = async () => { try { setLoadingTemplates(true); const res = await projectTemplatesApiService.getWorklenzTemplates(); if (res.done) { setTemplates(res.body); if (res.body.length > 0 && res.body[0].id) { templateSelected(res.body[0].id); await getSelectedTemplate(res.body[0].id); } } } catch (error) { logger.error('Error loading templates:', error); } finally { setLoadingTemplates(false); } }; const getCustomTemplates = async () => { try { setLoadingCustomTemplates(true); const res = await projectTemplatesApiService.getCustomTemplates(); if (res.done) { setCustomTemplates(res.body); } } catch (error) { logger.error('Error loading custom templates:', error); } finally { setLoadingCustomTemplates(false); } }; useEffect(() => { getTemplates(); }, []); const menuItems: MenuProps['items'] = templates.map(template => ({ key: template.id || '', label: template.name || t('untitled'), type: 'item', })); const handleMenuClick = (templateId: string) => { templateSelected(templateId); getSelectedTemplate(templateId); }; const filteredCustomTemplates = customTemplates.filter(template => template.name?.toLowerCase().includes(searchQuery.toLowerCase()) ); const renderTemplateDetails = () => { if (!selectedTemplate) { return ; } return (
{/* Description */}
{t('description')}
{selectedTemplate.description || t('noDescription')}
{/* Phase */}
{t('phase')}
{selectedTemplate.phases?.length ? ( selectedTemplate.phases.map(phase => ( {phase.name} )) ) : ( {t('noPhases')} )}
{/* Statuses */}
{t('statuses')}
{selectedTemplate.status?.length ? ( selectedTemplate.status.map(status => ( {status.name} )) ) : ( {t('noStatuses')} )}
{/* Priorities */}
{t('priorities')}
{selectedTemplate.priorities?.length ? ( selectedTemplate.priorities.map(priority => ( {priority.name} )) ) : ( {t('noPriorities')} )}
{/* Labels */}
{t('labels')}
{selectedTemplate.labels?.length ? ( selectedTemplate.labels.map(label => ( {label.name} )) ) : ( {t('noLabels')} )}
{/* Tasks */}
{t('tasks')}
{selectedTemplate.tasks?.length ? ( ( {item.name} )} /> ) : ( {t('noTasks')} )}
); }; const menuContent = (
{/* Menu Area */}
handleMenuClick(key)} style={{ width: 256 }} defaultSelectedKeys={[templates[0]?.id || '']} mode="inline" items={menuItems} />
{/* Content Area */}
Details {selectedTemplate?.image_url && ( {selectedTemplate.name} )} {renderTemplateDetails()}
); const handleCustomTemplateClick = (templateId: string) => { const updatedCustomTemplates = customTemplates.map(template => template.id === templateId ? { ...template, selected: true } : { ...template, selected: false } ); setCustomTemplates(updatedCustomTemplates); templateSelected(templateId); selectedTemplateType('custom'); }; const customTemplatesContent = (
} style={{ maxWidth: '300px' }} onChange={e => setSearchQuery(e.target.value)} /> ( handleCustomTemplateClick(item.id || '')} className={ item.selected && themeMode === 'dark' ? 'selected-custom-template-dark' : item.selected && themeMode === 'light' ? 'selected-custom-template' : '' } > {item.name} )} />
); const tabs = [ { key: '1', label: t('worklenzTemplates'), children: menuContent, }, { key: '2', label: t('yourTemplatesLibrary'), children: customTemplatesContent, }, ]; const handleTabChange = (key: string) => { if (key === '1') { getTemplates(); selectedTemplateType('worklenz'); } else { getCustomTemplates(); selectedTemplateType('custom'); } }; return (
{showBothTabs ? ( ) : ( menuContent )}
); }; export default TemplateDrawer;