diff --git a/components/FolderModal.css b/components/FolderModal.css new file mode 100644 index 0000000..d4f624a --- /dev/null +++ b/components/FolderModal.css @@ -0,0 +1,244 @@ +/* Folder Modal Styles */ +.folder-container { + padding: 1.5rem; + max-height: 70vh; + overflow-y: auto; +} + +.folder-form { + display: flex; + flex-direction: column; + gap: 2rem; +} + +/* Form Sections */ +.form-section { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.section-title { + font-size: 1.125rem; + font-weight: 600; + color: #374151; + margin: 0 0 0.5rem 0; + padding-bottom: 0.5rem; + border-bottom: 2px solid #e5e7eb; +} + +/* Form Layout */ +.form-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; +} + +.form-field { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.form-field label { + font-size: 0.875rem; + font-weight: 500; + color: #374151; +} + +.required { + color: #dc2626; +} + +/* Form Inputs */ +.form-field input, +.form-field textarea, +.form-field select { + padding: 0.75rem; + border: 1px solid #d1d5db; + border-radius: 0.5rem; + font-size: 0.875rem; + transition: border-color 0.2s, box-shadow 0.2s; + background-color: white; +} + +.form-field input:focus, +.form-field textarea:focus, +.form-field select:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +.form-field input:disabled, +.form-field textarea:disabled, +.form-field select:disabled { + background-color: #f9fafb; + color: #6b7280; + cursor: not-allowed; +} + +.form-field input::placeholder, +.form-field textarea::placeholder { + color: #9ca3af; +} + +/* Tag System */ +.tag-list { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin-bottom: 0.75rem; +} + +.tag-item { + display: flex; + align-items: center; + gap: 0.5rem; + background-color: #eff6ff; + color: #1d4ed8; + padding: 0.375rem 0.75rem; + border-radius: 9999px; + font-size: 0.875rem; + border: 1px solid #bfdbfe; +} + +.tag-remove { + display: flex; + align-items: center; + justify-content: center; + width: 1.25rem; + height: 1.25rem; + border: none; + background: none; + color: #1d4ed8; + cursor: pointer; + border-radius: 50%; + font-size: 1rem; + line-height: 1; + transition: background-color 0.2s; +} + +.tag-remove:hover { + background-color: #dbeafe; +} + +.tag-input-container { + display: flex; + gap: 0.5rem; + align-items: flex-end; +} + +.tag-input-container input { + flex: 1; +} + +.btn-add-tag { + padding: 0.75rem 1rem; + background-color: #3b82f6; + color: white; + border: none; + border-radius: 0.5rem; + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s; + white-space: nowrap; +} + +.btn-add-tag:hover { + background-color: #2563eb; +} + +/* Form Actions */ +.form-actions { + display: flex; + justify-content: flex-end; + gap: 0.75rem; + padding-top: 1rem; + border-top: 1px solid #e5e7eb; + margin-top: 1rem; +} + +.btn-cancel { + padding: 0.75rem 1.5rem; + background-color: white; + color: #374151; + border: 1px solid #d1d5db; + border-radius: 0.5rem; + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s; +} + +.btn-cancel:hover { + background-color: #f9fafb; + border-color: #9ca3af; +} + +.btn-submit { + padding: 0.75rem 1.5rem; + background-color: #059669; + color: white; + border: none; + border-radius: 0.5rem; + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s; +} + +.btn-submit:hover { + background-color: #047857; +} + +.btn-submit:disabled { + background-color: #9ca3af; + cursor: not-allowed; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .folder-container { + padding: 1rem; + } + + .form-row { + grid-template-columns: 1fr; + } + + .form-actions { + flex-direction: column-reverse; + } + + .btn-cancel, + .btn-submit { + width: 100%; + justify-content: center; + } + + .tag-input-container { + flex-direction: column; + align-items: stretch; + } +} + +/* Custom scrollbar for the container */ +.folder-container::-webkit-scrollbar { + width: 6px; +} + +.folder-container::-webkit-scrollbar-track { + background: #f1f5f9; + border-radius: 3px; +} + +.folder-container::-webkit-scrollbar-thumb { + background: #cbd5e1; + border-radius: 3px; +} + +.folder-container::-webkit-scrollbar-thumb:hover { + background: #94a3b8; +} diff --git a/components/FolderModal.tsx b/components/FolderModal.tsx new file mode 100644 index 0000000..67bd079 --- /dev/null +++ b/components/FolderModal.tsx @@ -0,0 +1,421 @@ +import React, { useState, memo } from 'react'; +import Modal from './ui/modal/Modal'; +import './FolderModal.css'; +import type { FolderData } from '../lib/4nk/models/FolderData'; + +interface FolderModalProps { + folder?: FolderData; + onSave?: (folderData: FolderData) => void; + onCancel?: () => void; + readOnly?: boolean; + isOpen: boolean; + onClose: () => void; +} + +const defaultFolder: FolderData = { + folderNumber: '', + name: '', + deedType: '', + description: '', + archived_description: '', + status: 'active', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + customers: [], + documents: [], + motes: [], + stakeholders: [] +}; + +function FolderModal({ + folder = defaultFolder, + onSave, + onCancel, + readOnly = false, + isOpen, + onClose +}: FolderModalProps) { + const [folderData, setFolderData] = useState(folder); + const [currentCustomer, setCurrentCustomer] = useState(''); + const [currentStakeholder, setCurrentStakeholder] = useState(''); + const [currentMote, setCurrentMote] = useState(''); + + if (!isOpen) return null; + + const handleInputChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + setFolderData(prev => ({ + ...prev, + [name]: value + })); + }; + + const addCustomer = () => { + if (currentCustomer.trim() && !folderData.customers.includes(currentCustomer.trim())) { + setFolderData(prev => ({ + ...prev, + customers: [...prev.customers, currentCustomer.trim()] + })); + setCurrentCustomer(''); + } + }; + + const removeCustomer = (customer: string) => { + setFolderData(prev => ({ + ...prev, + customers: prev.customers.filter(c => c !== customer) + })); + }; + + const addStakeholder = () => { + if (currentStakeholder.trim() && !folderData.stakeholders.includes(currentStakeholder.trim())) { + setFolderData(prev => ({ + ...prev, + stakeholders: [...prev.stakeholders, currentStakeholder.trim()] + })); + setCurrentStakeholder(''); + } + }; + + const removeStakeholder = (stakeholder: string) => { + setFolderData(prev => ({ + ...prev, + stakeholders: prev.stakeholders.filter(s => s !== stakeholder) + })); + }; + + const addMote = () => { + if (currentMote.trim() && !folderData.motes.includes(currentMote.trim())) { + setFolderData(prev => ({ + ...prev, + motes: [...prev.motes, currentMote.trim()] + })); + setCurrentMote(''); + } + }; + + const removeMote = (mote: string) => { + setFolderData(prev => ({ + ...prev, + motes: prev.motes.filter(m => m !== mote) + })); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + if (onSave) { + onSave({ + ...folderData, + updated_at: new Date().toISOString() + }); + } + }; + + const handleCancel = () => { + if (onCancel) { + onCancel(); + } else { + onClose(); + } + }; + + return ( + +
+
+
+

Informations principales

+
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+ +