UNPKG

@catalystlabs/awm

Version:

Appwrite Migration Tool - Schema management and code generation for Appwrite databases

193 lines (175 loc) 5.61 kB
'use client'; import { useState } from 'react'; import { Modal, Button, Form, Input, InputNumber, DatePicker, Toggle, Message, toaster } from 'rsuite'; export default function CreateDocumentModal({ collection, open, onClose, onSuccess }) { const [formValue, setFormValue] = useState({}); const [loading, setLoading] = useState(false); async function handleCreate() { try { setLoading(true); // Validate required fields const requiredFields = collection.attributes.filter(attr => attr.required); for (const field of requiredFields) { if (!formValue[field.key]) { toaster.push( <Message showIcon type="error" closable> {field.key} is required </Message>, { placement: 'topEnd', duration: 3000 } ); return; } } const response = await fetch(`/api/collections/${collection.$id}/documents`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ data: formValue }) }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to create document'); } toaster.push( <Message showIcon type="success" closable> Document created successfully </Message>, { placement: 'topEnd', duration: 3000 } ); setFormValue({}); onSuccess(); } catch (err) { toaster.push( <Message showIcon type="error" closable> {err.message} </Message>, { placement: 'topEnd', duration: 5000 } ); } finally { setLoading(false); } } function renderField(attribute) { const { key, type, required, array } = attribute; const commonProps = { name: key, placeholder: `Enter ${key}${array ? ' (comma separated)' : ''}`, value: formValue[key] || '', onChange: (value) => { setFormValue(prev => ({ ...prev, [key]: value })); } }; switch (type) { case 'string': case 'email': case 'url': return ( <Form.Group controlId={key}> <Form.ControlLabel> {key} {required && <span style={{ color: 'red' }}>*</span>} </Form.ControlLabel> <Input {...commonProps} /> {array && <Form.HelpText>Enter values separated by commas</Form.HelpText>} </Form.Group> ); case 'integer': return ( <Form.Group controlId={key}> <Form.ControlLabel> {key} {required && <span style={{ color: 'red' }}>*</span>} </Form.ControlLabel> <InputNumber {...commonProps} step={1} onChange={(value) => { setFormValue(prev => ({ ...prev, [key]: value })); }} /> </Form.Group> ); case 'float': return ( <Form.Group controlId={key}> <Form.ControlLabel> {key} {required && <span style={{ color: 'red' }}>*</span>} </Form.ControlLabel> <InputNumber {...commonProps} step={0.01} onChange={(value) => { setFormValue(prev => ({ ...prev, [key]: value })); }} /> </Form.Group> ); case 'boolean': return ( <Form.Group controlId={key}> <Form.ControlLabel> {key} {required && <span style={{ color: 'red' }}>*</span>} </Form.ControlLabel> <Toggle checked={formValue[key] || false} onChange={(checked) => { setFormValue(prev => ({ ...prev, [key]: checked })); }} /> </Form.Group> ); case 'datetime': return ( <Form.Group controlId={key}> <Form.ControlLabel> {key} {required && <span style={{ color: 'red' }}>*</span>} </Form.ControlLabel> <DatePicker format="yyyy-MM-dd HH:mm:ss" value={formValue[key] ? new Date(formValue[key]) : null} onChange={(date) => { setFormValue(prev => ({ ...prev, [key]: date ? date.toISOString() : null })); }} style={{ width: '100%' }} /> </Form.Group> ); default: return ( <Form.Group controlId={key}> <Form.ControlLabel> {key} {required && <span style={{ color: 'red' }}>*</span>} </Form.ControlLabel> <Input {...commonProps} as="textarea" rows={3} /> <Form.HelpText>Type: {type}</Form.HelpText> </Form.Group> ); } } return ( <Modal open={open} onClose={onClose} size="md" overflow={true} > <Modal.Header> <Modal.Title>Create New Document</Modal.Title> </Modal.Header> <Modal.Body> <Form fluid formValue={formValue}> {collection?.attributes.map((attr) => ( <div key={attr.key} style={{ marginBottom: '16px' }}> {renderField(attr)} </div> ))} </Form> </Modal.Body> <Modal.Footer> <Button onClick={onClose} appearance="subtle" disabled={loading}> Cancel </Button> <Button onClick={handleCreate} appearance="primary" loading={loading}> Create </Button> </Modal.Footer> </Modal> ); }