Skip to content

refactor(admin-frontend): tipo das props de cada campo fica no arquivo do campo - #217

Open
evertonschuster wants to merge 1 commit into
mainfrom
refactor/field-props-per-field
Open

evertonschuster wants to merge 1 commit into
mainfrom
refactor/field-props-per-field

Conversation

@evertonschuster

@evertonschuster evertonschuster commented Nov 11, 2026 •

Copy link
Copy Markdown
Owner

O que muda

O shared/form/fields/fields.types.ts passa a ser genérico. Ele não importa mais nada de shared/ui e não conhece nenhum campo. O tipo das props de cada campo e a lista das props omitidas ficam no arquivo do próprio campo, em components/, ao lado do primitivo que o campo renderiza. É o modelo que o #207 adotou para o SearchSelectField no commit 2ae5e6c.

A mudança é só de estrutura de tipos. Nenhum comportamento muda, e o barril fields/index.tsx continua exportando os mesmos 14 nomes de tipo, agora a partir do arquivo de cada campo. Nenhum consumidor fora de fields/ foi tocado.

Inventário

O que o fields.types.ts importava de shared/ui na main:

Import de shared/ui Tipo que o usava Campo Para onde foi
Input TextFieldProps, MaskedFieldProps, DateFieldProps TextField, MaskedField, DateField text-fields.tsx, masked-field.tsx, date-field.tsx
Textarea TextareaFieldProps TextareaField text-fields.tsx
InputGroupInput SearchFieldProps SearchField search-field.tsx
ColorSwatchPickerOption ColorFieldProps ColorField color-field.tsx
FormFieldControlProps ControlledFieldProps ControlledField controlled-field.tsx

Tipos que pertencem a um campo só, sem import de shared/ui:

Tipo Campo Para onde foi
CpfFieldProps (deriva de MaskedFieldProps) CpfField cpf-field.tsx
PhoneFieldProps (deriva de TextFieldProps) PhoneField phone-field.tsx
EmailFieldProps (deriva de TextFieldProps) EmailField email-field.tsx
BirthDateFieldProps (deriva de DateFieldProps) BirthDateField birth-date-field.tsx
SelectFieldOption, SelectFieldBaseProps (interno), SelectFieldProps SelectField select-field.tsx
FieldErrorProps FieldError field-error.tsx

Um campo construído sobre outro importa o tipo base do arquivo do campo que ele já renderiza: PhoneField e EmailField usam text-fields, CpfField usa masked-field e BirthDateField usa date-field. O teste do SelectField passou a importar SelectFieldOption de ./select-field.

O que ficou em fields.types.ts, exportado porque vários campos usam:

  • BaseFieldProps: TextField, TextareaField, MaskedField e DateField;
  • RegisterOwnedProps e FormFieldOwnedProps: os mesmos quatro, mais o SearchField;
  • WithOptionalLabel: CpfField, PhoneField, EmailField e BirthDateField;
  • FieldLabelPlacement: SelectField e SearchField, a união tipada uma vez só, como registra a ADR 0076.

Nenhum tipo exigiu escolha. Os tipos compartilhados são genéricos e ficam em fields.types.ts. Os derivados seguem a dependência que o componente já tem, e a API pública do barril não muda.

Orientação para os próximos campos

  • .claude/skills/agenza-form-field/SKILL.md: o tipo das props de um campo novo nasce no arquivo do campo e é reexportado de lá pelo barril. O fields.types.ts só guarda as peças compartilhadas e não importa de shared/ui.
  • apps/admin-frontend/docs/ARCHITECTURE.md: a mesma regra, na seção de componentes e formulários.

Não abri ADR nova. É uma convenção de organização local, reversível e sem efeito em fronteira, contrato, persistência ou operação, então se encaixa no guia de arquitetura e na skill (ADR 0088). Nenhuma ADR na main dizia onde ficam os tipos dos campos. A ADR 0091, que vem no #207, já registra o caso do SearchSelectField.

Relação com o #207

O #207 (claude/multi-select-component-d9018b) também mexe no fields.types.ts e no index.tsx. Por isso, o PR que entrar por último resolve um conflito pequeno nesses dois arquivos. Os dois exportam as mesmas peças genéricas, BaseFieldProps e FormFieldOwnedProps, e este PR não toca no SearchSelectField. Resolver o conflito é manter o fields.types.ts deste PR e a linha export { SearchSelectField, type SearchSelectFieldProps } ... do #207 no barril.

Este PR substitui a tentativa do #216, que foi fechado por escopo. Ele reaproveita a mesma divisão e vai além em dois pontos: também tira ControlledFieldProps e FieldErrorProps de fields.types.ts, e com isso o arquivo deixa de importar FormFieldControlProps de shared/ui/form-field.

Verificação

Rodado em apps/admin-frontend:

  • npm run format:check: ok;
  • npm run lint: 0 erros. Os 6 avisos react-refresh/only-export-components já existiam e estão fora de shared/form/fields; npx eslint src/shared/form/fields sai limpo;
  • npm run build: ok (tsc + vite build);
  • npx vitest run --coverage --exclude ".claude/**": 100 arquivos, 1092 testes passando, limiares de cobertura atendidos (linhas 98,08%, ramos 94,65%);
  • npm run check:docs (raiz): ok.

O fields.types.ts não tem nenhum import de @/shared/ui. Confirmei com grep.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor

    • Form field prop types are now organized with their corresponding fields, while shared types remain available centrally. Existing field exports and rendered behavior are unchanged.
  • Documentation

    • Updated form development guidance to reflect the organization of field types and shared form types.

…o do campo

fields.types.ts deixa de importar de shared/ui e de conhecer os campos: guarda
só BaseFieldProps, RegisterOwnedProps, FormFieldOwnedProps, WithOptionalLabel e
FieldLabelPlacement. O tipo das props de cada campo e a lista das props
omitidas passam para o arquivo do próprio campo em components/, e o barril
reexporta os mesmos nomes a partir deles. A skill de formulário e o guia de
arquitetura dizem onde nasce o tipo de um campo novo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

Field-specific prop types now live in their component files instead of fields.types.ts. The barrel re-exports the component types. Architecture and field-authoring documentation describe the updated type ownership rules.

Changes: Field Prop Type Ownership

Layer / File(s) Summary
Shared and primitive field contracts
apps/admin-frontend/src/shared/form/fields/fields.types.ts, apps/admin-frontend/src/shared/form/fields/components/text-fields.tsx, apps/admin-frontend/src/shared/form/fields/components/masked-field.tsx, apps/admin-frontend/src/shared/form/fields/components/date-field.tsx
fields.types.ts now exports shared field types. Text, masked, and date components declare their prop types using those shared types and the relevant primitive props.
Component-specific prop types
apps/admin-frontend/src/shared/form/fields/components/*-field.tsx, apps/admin-frontend/src/shared/form/fields/components/controlled-field.tsx, apps/admin-frontend/src/shared/form/fields/components/field-error.tsx, apps/admin-frontend/src/shared/form/fields/components/select-field.test.tsx
Field-specific prop types move into their component files. SelectFieldOption values use the selected form field’s path value, and the select test imports the type from select-field.
Barrel exports and type-location guidance
apps/admin-frontend/src/shared/form/fields/index.tsx, apps/admin-frontend/docs/ARCHITECTURE.md, .claude/skills/agenza-form-field/SKILL.md
The barrel re-exports each component’s prop types, including FieldErrorProps and SelectFieldOption. The architecture documentation and field-authoring guidance describe where field prop types belong.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Refactor

Possibly related PRs

Merge Risk: Minimal · up to 7e55d

This refactor moves field prop types next to their components and updates the related documentation, with no behavior change. No merge-blocking risk was found in the changed code. The CI failures are in backend builds caused by a dependency vulnerability advisory and are not connected to these frontend changes.

Pre-merge checks: Passed 5

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: moving each field's prop type into its field file in admin-frontend.
Docstring Coverage Passed No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 0 functions across 15 files. (2 skipped: 2 unsupported.)

Finishing Touches

Generate docstrings

  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/admin-frontend/src/shared/form/fields/components/birth-date-field.tsx

typescript-eslint does not support TS 7.0.
Please see https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/#running-side-by-side-with-typescript-6.0 to run typescript-eslint using the TS 6 API.
See also typescript-eslint/typescript-eslint#10940 for tracking typescript-eslint's support for TS >=7.1

Oops! Something went wrong! :(

ESLint: 10.14.0

Error: typescript-eslint does not support TS 7.0.
at Object. (/.eslint-tmp/node_modules/typescript-eslint/dist/index.js:52:11)
at Module._compile (node:internal/modules/cjs/loader:1929:14)
at Object..js (node:internal/modules/cjs/loader:2060:10)
at Module.load (node:internal/modules/cjs/loader:1651:32)
at Module._load (node:internal/modules/cjs/loader:1443:12)
at wrapModuleLoad (node:internal/modules/cjs/loader:261:19)
at loadCJSModuleWithModuleLoad (node:internal/modules/esm/translators:372:15)
at ModuleWrap. (node:internal/modules/esm/translators:244:9)
at ModuleJob.run (node:internal/modules/esm/module_job:561:25)
at async node:internal/modules/esm/loader:647:26

apps/admin-frontend/src/shared/form/fields/components/color-field.tsx

ESLint skipped: the matched ESLint configuration already failed (config-incompatibility).

apps/admin-frontend/src/shared/form/fields/components/controlled-field.tsx

ESLint skipped: the matched ESLint configuration already failed (config-incompatibility).

  • 12 others

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a7975844-c335-40af-84fb-dcfb7c91359e
Commits

Reviewing files that changed from the base of the PR and between 0210f9b and 7e55d0d.

Files selected for processing: 17

  • .claude/skills/agenza-form-field/SKILL.md
  • apps/admin-frontend/docs/ARCHITECTURE.md
  • apps/admin-frontend/src/shared/form/fields/components/birth-date-field.tsx
  • apps/admin-frontend/src/shared/form/fields/components/color-field.tsx
  • apps/admin-frontend/src/shared/form/fields/components/controlled-field.tsx
  • apps/admin-frontend/src/shared/form/fields/components/cpf-field.tsx
  • apps/admin-frontend/src/shared/form/fields/components/date-field.tsx
  • apps/admin-frontend/src/shared/form/fields/components/email-field.tsx
  • apps/admin-frontend/src/shared/form/fields/components/field-error.tsx
  • apps/admin-frontend/src/shared/form/fields/components/masked-field.tsx
  • apps/admin-frontend/src/shared/form/fields/components/phone-field.tsx
  • apps/admin-frontend/src/shared/form/fields/components/search-field.tsx
  • apps/admin-frontend/src/shared/form/fields/components/select-field.test.tsx
  • apps/admin-frontend/src/shared/form/fields/components/select-field.tsx
  • apps/admin-frontend/src/shared/form/fields/components/text-fields.tsx
  • apps/admin-frontend/src/shared/form/fields/fields.types.ts
  • apps/admin-frontend/src/shared/form/fields/index.tsx

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant