AI Skill Report Card

Generating Table Index Files

A-85·May 7, 2026·Source: Web
15 / 15
TypeScript
// Variant A: Tab + Versioned + Non-Editable (External Form) export interface ForwardEquipeRefProps { addEquipe: () => void; } export default forwardRef<ForwardEquipeRefProps>((props: any, ref) => { const [form] = Form.useForm(); const [data, setData] = useState<DataType[]>([]); const [openForm, setOpenForm] = useState<boolean>(false); const [record, setRecord] = useState<Pessoal.Namespace.Equipe>(); const { selectedVersao } = useModel('global'); const { equipes, getEquipes } = useModel('pessoal.equipe.model'); const [queryStringParams, setQueryStringParams] = useState<Pessoal.Namespace.Equipe.EquipeQueryStringParams>(defaultQueryStringParams); const addEquipe = () => { setRecord(undefined); setOpenForm(true); }; useImperativeHandle(ref, () => ({ addEquipe })); return ( <> <SimpleTable loading={false} columns={mergedColumns} dataSource={data} ignoreColumnKeys={!selectedVersao?.id ? columns.map(c => c.key as string) : ['acoes']} onChange={(pagination, filters, sorter: any) => { // Standard pagination + filtering logic }} pagination={{ total: equipes?.count, current: queryStringParams.page, pageSize: queryStringParams.page_size, }} /> <FormEquipe open={openForm} setOpen={setOpenForm} record={record} /> </> ); });
Recommendation
Add a decision tree diagram or flowchart to make the variant selection process even faster
15 / 15

Step 1: Determine Pattern Variant

Decision Matrix:

  • Variant A: Tab + Versioned + Non-Editable (External Form) - forwardRef, uses selectedVersao, opens form dialog
  • Variant B: Standalone Page + Non-Editable - No forwardRef, add button in own PageContainer
  • Variant C: Tab + Versioned + Editable Inline - forwardRef, uses selectedVersao, EditableCell + mergedColumns
  • Variant D: Tab + Non-Versioned + Editable Inline - forwardRef, no selectedVersao, EditableCell + mergedColumns

Step 2: Set Up Core Structure

Progress:

  • Import statements and interfaces
  • State management and hooks
  • Data fetching effects
  • Column definitions
  • SimpleTable configuration
  • Form/modal components (if applicable)

Step 3: Configure Columns

Column type mapping:

  • type: 'boolean' for true/false fields
  • type: 'date' with dateProps for date fields
  • type: 'filter' with filters array for enum values
  • type: 'select' with component for relationship fields
  • type: 'percent' | 'money' | 'number' for numeric fields
  • No type for basic text columns

Step 4: Implement ignoreColumnKeys Logic

TypeScript
// Non-versioned standalone ignoreColumnKeys={['acoes']} // Versioned tab ignoreColumnKeys={!selectedVersao?.id ? columns.map(c => c.key as string) : ['acoes']} // Editable (versioned) ignoreColumnKeys={editingKey !== '' || !selectedVersao?.id ? columns.map(c => c.key as string) : ['acoes']} // Editable (non-versioned) ignoreColumnKeys={editingKey !== '' ? columns.map(c => c.key as string) : ['acoes']}

Step 5: Add Pagination and Filtering

All paginated tables use identical onChange structure with field mapping for __label columns back to API parameters.

Recommendation
Include more error handling patterns and common debugging scenarios in the examples
18 / 20

Example 1 - Variant B (Standalone Page):

TypeScript
export default () => { const [data, setData] = useState<VersaoType[]>([]); const [openForm, setOpenForm] = useState(false); const [record, setRecord] = useState<Planejamento.Versao.Versao>(); const { versoes, getVersoes, deleteVersao } = useModel('planejamento.versao.model'); const columns: SimpleTableColumnType<VersaoType>[] = [ { title: 'Nome', dataIndex: 'nome', key: 'nome', minWidth: 200, }, { title: 'Tipo', dataIndex: 'tipo__label', key: 'tipo__label', type: 'filter', filters: [ { text: 'Budget', value: 'Budget' }, { text: 'Forecast', value: 'Forecast' }, ], }, { title: 'Ações', dataIndex: 'acoes', key: 'acoes', render: (_, record) => ( <Space> <Button icon={<EditOutlined />} onClick={() => { setRecord(record); setOpenForm(true); }} /> <Popconfirm title="Confirma Deletar?" onConfirm={() => deleteVersao(record.id)}> <Button icon={<DeleteOutlined />} /> </Popconfirm> </Space> ), }, ]; return ( <PageContainer header={{ title: 'Versões' }} extra={<Button onClick={() => setOpenForm(true)}>Criar Versão</Button>} > <SimpleTable columns={columns} dataSource={data} ignoreColumnKeys={['acoes']} /> <FormEditCreate open={openForm} setOpen={setOpenForm} record={record} /> </PageContainer> ); };

Example 2 - Variant C (Editable Inline):

TypeScript
const EditableCell: React.FC<EditableCellProps> = ({ editing, inputType, children, formName, ...restProps }) => { const inputNodeMap = { sindicato: <SelectSindicato />, data: <DatePicker.MonthPicker format="MMM/YYYY" />, percent: <InputPercent max={100} />, }; return ( <td {...restProps}> {editing ? ( <Form.Item name={formName} style={{ margin: 0 }}> {inputNodeMap[inputType]} </Form.Item> ) : children} </td> ); }; export default forwardRef<ForwardDissidioRefProps>((props, ref) => { const [form] = Form.useForm(); const [data, setData] = useState<DataType[]>([]); const [editingKey, setEditingKey] = useState(''); const isEditing = (record: DataType) => record.key === editingKey; const mergedColumns = columns.map(col => { if (!col.editable) return col; return { ...col, onCell: (record: DataType) => ({ record, inputType: col.dataIndex, formName: col.dataIndex, editing: isEditing(record), }), }; }); const addDissidio = () => { const key = Date.now().toString(); const record = { key, sindicato: undefined, data: undefined, percent: undefined }; setData(prev => [record, ...prev]); edit(record); }; useImperativeHandle(ref, () => ({ addDissidio })); return ( <Form form={form} component={false}> <SimpleTable components={{ body: { cell: EditableCell } }} columns={mergedColumns} dataSource={data} ignoreColumnKeys={editingKey !== '' || !selectedVersao?.id ? columns.map(c => c.key as string) : ['acoes']} /> </Form> ); });
Recommendation
Consider adding performance optimization tips for large datasets or complex column configurations

Data Mapping:

  • Non-editable: Use spread pattern { key: c.id.toString(), ...c }
  • Editable: Explicit fields { key: c.id.toString(), id: c.id, nome: c.nome }

Column Keys:

  • Use API field names exactly: cargo__label, sindicato__nome, is_active
  • Actions column always uses key: 'acoes', dataIndex: 'acoes'

Filter Mapping:

  • __label columns need mapping in onChange: cargo__labelcargo
  • Static enum filters use full array: classificacao: filters[curr]
  • Select filters use .at(0): cargo: filters[curr]?.at(0)

Parent Containers:

  • Root tabs: PageContainer + Spin + SelectVersao with add button in extra
  • Intermediate tabs: Just Tabs with add button in tabBarExtraContent
  • Standalone pages: Add button in own PageContainer extra

Don't:

  • Mix spread and explicit field patterns in same codebase area
  • Put add buttons inside tab components (they go in parent containers)
  • Use selectedVersao in non-versioned variants
  • Forget to map __label column keys to API parameters in onChange
  • Use type: 'select' for static enum values (use type: 'filter' instead)

Always:

  • Match dataIndex to API response field names exactly
  • Include key property matching dataIndex for all columns
  • Use forwardRef + useImperativeHandle for all tab components
  • Set minWidth on columns to prevent layout issues
  • Include fixed: 'right' on actions column
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
15/15
Workflow
15/15
Examples
18/20
Completeness
18/20
Format
15/15
Conciseness
14/15