import React, {useState} from 'react'; import { useBase, useRecords, useGlobalConfig, expandRecord, TablePickerSynced, ViewPickerSynced, FieldPickerSynced, FormField, Input, Button, Box, Icon, } from '@airtable/blocks/ui'; import {FieldType} from '@airtable/blocks/models'; export default function TodoApp() { const base = useBase(); // Read the user's choice for which table and view to use from globalConfig. const globalConfig = useGlobalConfig(); const tableId = globalConfig.get('selectedTableId'); const viewId = globalConfig.get('selectedViewId'); const doneFieldId = globalConfig.get('selectedDoneFieldId'); const table = base.getTableByIdIfExists(tableId); const view = table ? table.getViewByIdIfExists(viewId) : null; const doneField = table ? table.getFieldByIdIfExists(doneFieldId) : null; // Don't need to fetch records if doneField doesn't exist (the field or it's parent table may // have been deleted, or may not have been selected yet.) const records = useRecords(doneField ? view : null, { fields: doneField ? [table.primaryField, doneField] : [], }); const tasks = records ? records.map(record => { return <Task key={record.id} record={record} table={table} doneField={doneField} />; }) : null; return ( <div> <Box padding={3} borderBottom="thick"> <FormField label="Table"> <TablePickerSynced globalConfigKey="selectedTableId" /> </FormField> <FormField label="View"> <ViewPickerSynced table={table} globalConfigKey="selectedViewId" /> </FormField> <FormField label="Field" marginBottom={0}> <FieldPickerSynced table={table} globalConfigKey="selectedDoneFieldId" placeholder="Pick a 'done' field..." allowedTypes={[FieldType.CHECKBOX]} /> </FormField> </Box> {tasks} {table && doneField && <AddTaskForm table={table} />} </div> ); } function Task({record, table, doneField}) { return ( <Box fontSize={4} paddingX={3} paddingY={2} marginRight={-2} borderBottom="default" display="flex" alignItems="center" > <TaskDoneCheckbox table={table} record={record} doneField={doneField} /> <a style={{cursor: 'pointer', flex: 'auto', padding: 8}} onClick={() => { expandRecord(record); }} > {record.name || 'Unnamed record'} </a> <TaskDeleteButton table={table} record={record} /> </Box> ); } function TaskDoneCheckbox({table, record, doneField}) { function onChange(event) { table.updateRecordAsync(record, { [doneField.id]: event.currentTarget.checked, }); } const permissionCheck = table.checkPermissionsForUpdateRecord(record, { [doneField.id]: undefined, }); return ( <input type="checkbox" checked={!!record.getCellValue(doneField)} onChange={onChange} style={{marginRight: 8}} disabled={!permissionCheck.hasPermission} /> ); } function TaskDeleteButton({table, record}) { function onClick() { table.deleteRecordAsync(record); } return ( <Button variant="secondary" marginLeft={1} onClick={onClick} disabled={!table.hasPermissionToDeleteRecord(record)} > <Icon name="x" style={{display: 'flex'}} /> </Button> ); } function AddTaskForm({table}) { const [taskName, setTaskName] = useState(''); function onInputChange(event) { setTaskName(event.currentTarget.value); } function onSubmit(event) { event.preventDefault(); table.createRecordAsync({ [table.primaryField.id]: taskName, }); setTaskName(''); } // check whether or not the user is allowed to create records with values in the primary field. // if not, disable the form. const isFormEnabled = table.hasPermissionToCreateRecord({ [table.primaryField.id]: undefined, }); return ( <form onSubmit={onSubmit}> <Box display="flex" padding={3}> <Input flex="auto" value={taskName} placeholder="New task" onChange={onInputChange} disabled={!isFormEnabled} /> <Button variant="primary" marginLeft={2} type="submit" disabled={!isFormEnabled}> Add </Button> </Box> </form> ); }