@tailor-platform/erp-kit 0.0.1 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +196 -28
- package/dist/cli.js +914 -0
- package/package.json +67 -8
- package/schemas/app-compose/actors.yml +34 -0
- package/schemas/app-compose/business-flow.yml +50 -0
- package/schemas/app-compose/requirements.yml +33 -0
- package/schemas/app-compose/resolver.yml +47 -0
- package/schemas/app-compose/screen.yml +81 -0
- package/schemas/app-compose/story.yml +67 -0
- package/schemas/module/command.yml +52 -0
- package/schemas/module/feature.yml +58 -0
- package/schemas/module/model.yml +70 -0
- package/schemas/module/module.yml +50 -0
- package/skills/1-module-docs/SKILL.md +111 -0
- package/skills/1-module-docs/references/structure.md +22 -0
- package/skills/2-module-feature-breakdown/SKILL.md +72 -0
- package/skills/2-module-feature-breakdown/references/commands.md +48 -0
- package/skills/2-module-feature-breakdown/references/models.md +29 -0
- package/skills/2-module-feature-breakdown/references/structure.md +22 -0
- package/skills/3-module-doc-review/SKILL.md +236 -0
- package/skills/3-module-doc-review/references/commands.md +54 -0
- package/skills/3-module-doc-review/references/models.md +29 -0
- package/skills/3-module-doc-review/references/testing.md +37 -0
- package/skills/4-module-tdd-implementation/SKILL.md +74 -0
- package/skills/4-module-tdd-implementation/references/commands.md +45 -0
- package/skills/4-module-tdd-implementation/references/db-relations.md +69 -0
- package/skills/4-module-tdd-implementation/references/errors.md +7 -0
- package/skills/4-module-tdd-implementation/references/exports.md +8 -0
- package/skills/4-module-tdd-implementation/references/models.md +30 -0
- package/skills/4-module-tdd-implementation/references/structure.md +22 -0
- package/skills/4-module-tdd-implementation/references/testing.md +37 -0
- package/skills/5-module-implementation-review/SKILL.md +408 -0
- package/skills/5-module-implementation-review/references/commands.md +45 -0
- package/skills/5-module-implementation-review/references/errors.md +7 -0
- package/skills/5-module-implementation-review/references/exports.md +8 -0
- package/skills/5-module-implementation-review/references/models.md +30 -0
- package/skills/5-module-implementation-review/references/testing.md +29 -0
- package/skills/app-compose-1-requirement-analysis/SKILL.md +89 -0
- package/skills/app-compose-1-requirement-analysis/references/structure.md +27 -0
- package/skills/app-compose-2-requirements-breakdown/SKILL.md +95 -0
- package/skills/app-compose-2-requirements-breakdown/references/screen-detailview.md +106 -0
- package/skills/app-compose-2-requirements-breakdown/references/screen-form.md +139 -0
- package/skills/app-compose-2-requirements-breakdown/references/screen-listview.md +153 -0
- package/skills/app-compose-2-requirements-breakdown/references/structure.md +27 -0
- package/skills/app-compose-3-doc-review/SKILL.md +116 -0
- package/skills/app-compose-3-doc-review/references/structure.md +27 -0
- package/skills/app-compose-4-design-mock/SKILL.md +256 -0
- package/skills/app-compose-4-design-mock/references/component.md +50 -0
- package/skills/app-compose-4-design-mock/references/screen-detailview.md +106 -0
- package/skills/app-compose-4-design-mock/references/screen-form.md +139 -0
- package/skills/app-compose-4-design-mock/references/screen-listview.md +153 -0
- package/skills/app-compose-4-design-mock/references/structure.md +27 -0
- package/skills/app-compose-5-design-mock-review/SKILL.md +290 -0
- package/skills/app-compose-5-design-mock-review/references/component.md +50 -0
- package/skills/app-compose-5-design-mock-review/references/screen-detailview.md +106 -0
- package/skills/app-compose-5-design-mock-review/references/screen-form.md +139 -0
- package/skills/app-compose-5-design-mock-review/references/screen-listview.md +153 -0
- package/skills/app-compose-6-implementation-spec/SKILL.md +127 -0
- package/skills/app-compose-6-implementation-spec/references/auth.md +72 -0
- package/skills/app-compose-6-implementation-spec/references/structure.md +27 -0
- package/skills/mock-scenario/SKILL.md +118 -0
- package/src/app.ts +1 -0
- package/src/cli.ts +120 -0
- package/src/commands/check.test.ts +30 -0
- package/src/commands/check.ts +66 -0
- package/src/commands/init.test.ts +88 -0
- package/src/commands/init.ts +120 -0
- package/src/commands/mock/index.ts +53 -0
- package/src/commands/mock/start.ts +179 -0
- package/src/commands/mock/validate.test.ts +185 -0
- package/src/commands/mock/validate.ts +198 -0
- package/src/commands/scaffold.test.ts +76 -0
- package/src/commands/scaffold.ts +119 -0
- package/src/commands/sync-check.test.ts +125 -0
- package/src/commands/sync-check.ts +182 -0
- package/src/integration.test.ts +63 -0
- package/src/mdschema.ts +48 -0
- package/src/mockServer.ts +55 -0
- package/src/module.ts +86 -0
- package/src/modules/accounting/.gitkeep +0 -0
- package/src/modules/coa-management/.gitkeep +0 -0
- package/src/modules/inventory/.gitkeep +0 -0
- package/src/modules/manufacturing/.gitkeep +0 -0
- package/src/modules/primitives/README.md +39 -0
- package/src/modules/primitives/command/activateCategory.test.ts +75 -0
- package/src/modules/primitives/command/activateCategory.ts +50 -0
- package/src/modules/primitives/command/activateCurrency.test.ts +70 -0
- package/src/modules/primitives/command/activateCurrency.ts +50 -0
- package/src/modules/primitives/command/activateUnit.test.ts +53 -0
- package/src/modules/primitives/command/activateUnit.ts +50 -0
- package/src/modules/primitives/command/convertAmount.test.ts +275 -0
- package/src/modules/primitives/command/convertAmount.ts +126 -0
- package/src/modules/primitives/command/convertQuantity.test.ts +219 -0
- package/src/modules/primitives/command/convertQuantity.ts +73 -0
- package/src/modules/primitives/command/createCategory.test.ts +126 -0
- package/src/modules/primitives/command/createCategory.ts +89 -0
- package/src/modules/primitives/command/createCurrency.test.ts +191 -0
- package/src/modules/primitives/command/createCurrency.ts +77 -0
- package/src/modules/primitives/command/createExchangeRate.test.ts +216 -0
- package/src/modules/primitives/command/createExchangeRate.ts +91 -0
- package/src/modules/primitives/command/createUnit.test.ts +214 -0
- package/src/modules/primitives/command/createUnit.ts +88 -0
- package/src/modules/primitives/command/deactivateCategory.test.ts +97 -0
- package/src/modules/primitives/command/deactivateCategory.ts +62 -0
- package/src/modules/primitives/command/deactivateCurrency.test.ts +85 -0
- package/src/modules/primitives/command/deactivateCurrency.ts +55 -0
- package/src/modules/primitives/command/deactivateUnit.test.ts +78 -0
- package/src/modules/primitives/command/deactivateUnit.ts +62 -0
- package/src/modules/primitives/command/setBaseCurrency.test.ts +98 -0
- package/src/modules/primitives/command/setBaseCurrency.ts +74 -0
- package/src/modules/primitives/command/setReferenceUnit.test.ts +108 -0
- package/src/modules/primitives/command/setReferenceUnit.ts +84 -0
- package/src/modules/primitives/db/currency.ts +30 -0
- package/src/modules/primitives/db/exchangeRate.ts +28 -0
- package/src/modules/primitives/db/unit.ts +32 -0
- package/src/modules/primitives/db/uomCategory.ts +32 -0
- package/src/modules/primitives/docs/commands/ActivateCategory.md +34 -0
- package/src/modules/primitives/docs/commands/ActivateCurrency.md +33 -0
- package/src/modules/primitives/docs/commands/ActivateUnit.md +34 -0
- package/src/modules/primitives/docs/commands/ConvertAmount.md +50 -0
- package/src/modules/primitives/docs/commands/ConvertQuantity.md +43 -0
- package/src/modules/primitives/docs/commands/CreateCategory.md +44 -0
- package/src/modules/primitives/docs/commands/CreateCurrency.md +47 -0
- package/src/modules/primitives/docs/commands/CreateExchangeRate.md +48 -0
- package/src/modules/primitives/docs/commands/CreateUnit.md +48 -0
- package/src/modules/primitives/docs/commands/DeactivateCategory.md +38 -0
- package/src/modules/primitives/docs/commands/DeactivateCurrency.md +38 -0
- package/src/modules/primitives/docs/commands/DeactivateUnit.md +38 -0
- package/src/modules/primitives/docs/commands/SetBaseCurrency.md +39 -0
- package/src/modules/primitives/docs/commands/SetReferenceUnit.md +43 -0
- package/src/modules/primitives/docs/features/currency-definitions.md +55 -0
- package/src/modules/primitives/docs/features/exchange-rates.md +61 -0
- package/src/modules/primitives/docs/features/unit-conversion.md +66 -0
- package/src/modules/primitives/docs/features/uom-categories.md +52 -0
- package/src/modules/primitives/docs/models/Currency.md +45 -0
- package/src/modules/primitives/docs/models/ExchangeRate.md +33 -0
- package/src/modules/primitives/docs/models/Unit.md +46 -0
- package/src/modules/primitives/docs/models/UoMCategory.md +44 -0
- package/src/modules/primitives/generated/kysely-tailordb.ts +95 -0
- package/src/modules/primitives/index.ts +40 -0
- package/src/modules/primitives/lib/errors.ts +138 -0
- package/src/modules/primitives/lib/types.ts +20 -0
- package/src/modules/primitives/module.ts +66 -0
- package/src/modules/primitives/permissions.ts +18 -0
- package/src/modules/primitives/tailor.config.ts +11 -0
- package/src/modules/primitives/testing/fixtures.ts +161 -0
- package/src/modules/product-management/.gitkeep +0 -0
- package/src/modules/purchase/.gitkeep +0 -0
- package/src/modules/sales/.gitkeep +0 -0
- package/src/modules/shared/createContext.test.ts +39 -0
- package/src/modules/shared/createContext.ts +15 -0
- package/src/modules/shared/defineCommand.test.ts +42 -0
- package/src/modules/shared/defineCommand.ts +19 -0
- package/src/modules/shared/definePermissions.test.ts +146 -0
- package/src/modules/shared/definePermissions.ts +94 -0
- package/src/modules/shared/entityTypes.ts +15 -0
- package/src/modules/shared/errors.ts +22 -0
- package/src/modules/shared/index.ts +1 -0
- package/src/modules/shared/internal.ts +13 -0
- package/src/modules/shared/requirePermission.test.ts +47 -0
- package/src/modules/shared/requirePermission.ts +8 -0
- package/src/modules/shared/types.ts +4 -0
- package/src/modules/supplier-management/.gitkeep +0 -0
- package/src/modules/supplier-portal/.gitkeep +0 -0
- package/src/modules/testing/index.ts +120 -0
- package/src/modules/user-management/README.md +38 -0
- package/src/modules/user-management/command/activateUser.test.ts +112 -0
- package/src/modules/user-management/command/activateUser.ts +67 -0
- package/src/modules/user-management/command/assignPermissionToRole.test.ts +119 -0
- package/src/modules/user-management/command/assignPermissionToRole.ts +87 -0
- package/src/modules/user-management/command/assignRoleToUser.test.ts +162 -0
- package/src/modules/user-management/command/assignRoleToUser.ts +93 -0
- package/src/modules/user-management/command/createPermission.test.ts +143 -0
- package/src/modules/user-management/command/createPermission.ts +66 -0
- package/src/modules/user-management/command/createRole.test.ts +115 -0
- package/src/modules/user-management/command/createRole.ts +52 -0
- package/src/modules/user-management/command/createUser.test.ts +198 -0
- package/src/modules/user-management/command/createUser.ts +85 -0
- package/src/modules/user-management/command/deactivateUser.test.ts +112 -0
- package/src/modules/user-management/command/deactivateUser.ts +67 -0
- package/src/modules/user-management/command/logAuditEvent.test.ts +179 -0
- package/src/modules/user-management/command/logAuditEvent.ts +59 -0
- package/src/modules/user-management/command/reactivateUser.test.ts +115 -0
- package/src/modules/user-management/command/reactivateUser.ts +67 -0
- package/src/modules/user-management/command/revokePermissionFromRole.test.ts +112 -0
- package/src/modules/user-management/command/revokePermissionFromRole.ts +81 -0
- package/src/modules/user-management/command/revokeRoleFromUser.test.ts +112 -0
- package/src/modules/user-management/command/revokeRoleFromUser.ts +81 -0
- package/src/modules/user-management/db/auditEvent.ts +47 -0
- package/src/modules/user-management/db/permission.ts +31 -0
- package/src/modules/user-management/db/role.ts +28 -0
- package/src/modules/user-management/db/rolePermission.ts +44 -0
- package/src/modules/user-management/db/user.ts +38 -0
- package/src/modules/user-management/db/userRole.ts +44 -0
- package/src/modules/user-management/docs/commands/ActivateUser.md +36 -0
- package/src/modules/user-management/docs/commands/AssignPermissionToRole.md +39 -0
- package/src/modules/user-management/docs/commands/AssignRoleToUser.md +43 -0
- package/src/modules/user-management/docs/commands/CreatePermission.md +35 -0
- package/src/modules/user-management/docs/commands/CreateRole.md +35 -0
- package/src/modules/user-management/docs/commands/CreateUser.md +41 -0
- package/src/modules/user-management/docs/commands/DeactivateUser.md +38 -0
- package/src/modules/user-management/docs/commands/LogAuditEvent.md +37 -0
- package/src/modules/user-management/docs/commands/ReactivateUser.md +37 -0
- package/src/modules/user-management/docs/commands/RevokePermissionFromRole.md +40 -0
- package/src/modules/user-management/docs/commands/RevokeRoleFromUser.md +40 -0
- package/src/modules/user-management/docs/features/audit-trail.md +80 -0
- package/src/modules/user-management/docs/features/role-based-access-control.md +76 -0
- package/src/modules/user-management/docs/features/user-account-management.md +64 -0
- package/src/modules/user-management/docs/models/AuditEvent.md +34 -0
- package/src/modules/user-management/docs/models/Permission.md +31 -0
- package/src/modules/user-management/docs/models/Role.md +31 -0
- package/src/modules/user-management/docs/models/RolePermission.md +33 -0
- package/src/modules/user-management/docs/models/User.md +47 -0
- package/src/modules/user-management/docs/models/UserRole.md +34 -0
- package/src/modules/user-management/docs/plans/2026-01-30-flattened-permissions-design.md +52 -0
- package/src/modules/user-management/executor/recomputeOnRolePermissionChange.ts +61 -0
- package/src/modules/user-management/generated/enums.ts +24 -0
- package/src/modules/user-management/generated/kysely-tailordb.ts +112 -0
- package/src/modules/user-management/index.ts +32 -0
- package/src/modules/user-management/lib/errors.ts +81 -0
- package/src/modules/user-management/lib/recomputeUserPermissions.ts +53 -0
- package/src/modules/user-management/lib/types.ts +31 -0
- package/src/modules/user-management/module.ts +77 -0
- package/src/modules/user-management/permissions.ts +15 -0
- package/src/modules/user-management/tailor.config.ts +11 -0
- package/src/modules/user-management/testing/fixtures.ts +98 -0
- package/src/schemas.ts +25 -0
- package/src/testing.ts +10 -0
- package/src/util.ts +3 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Application Directory Structure
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
{app_name}/
|
|
5
|
+
├── backend/
|
|
6
|
+
│ ├── src/
|
|
7
|
+
│ │ ├── modules.ts # Declaring module usage
|
|
8
|
+
│ │ ├── modules/
|
|
9
|
+
│ │ │ └── {module-name}/ # Module-specific directory
|
|
10
|
+
│ │ │ ├── resolvers/ # API Definition to expose graphql apis
|
|
11
|
+
│ │ │ └── executors/ # PubSub Automation (one file per declaration)
|
|
12
|
+
│ │ └── generated/ # Auto-generated code (do not edit)
|
|
13
|
+
│ └── tailor.config.ts # tailor application config
|
|
14
|
+
│
|
|
15
|
+
└── frontend/
|
|
16
|
+
└── src/
|
|
17
|
+
├── pages/ # File-based routing (auto-discovered by Vite plugin)
|
|
18
|
+
│ └── {page-path}/
|
|
19
|
+
│ ├── page.tsx
|
|
20
|
+
│ └── {page-path}/
|
|
21
|
+
│ ├── components/
|
|
22
|
+
│ └── page.tsx
|
|
23
|
+
├── components/
|
|
24
|
+
│ └── ui/ # Generic UI components
|
|
25
|
+
├── graphql/ # gql.tada settings
|
|
26
|
+
└── providers/ # react providers
|
|
27
|
+
```
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: app-compose-5-design-mock-review
|
|
3
|
+
description: Review design mockups (.pen files) against screen specifications. Use after completing design mockups with app-compose-4-design-mock. Validates visual consistency, detects regressions, and fixes layout issues.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Design Mockup Review Workflow
|
|
7
|
+
|
|
8
|
+
Review visual design mockups against Tier 3 screen documentation. Detect and fix regressions, layout issues, and specification mismatches.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
- `docs/screen/*.md` (screen specifications)
|
|
13
|
+
- `docs/design.pen` (design mockups from app-compose-4-design-mock)
|
|
14
|
+
|
|
15
|
+
## Workflow Phases
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
INVENTORY → PARITY CHECK → VISUAL REVIEW → REGRESSION FIX → VALIDATE
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Phase 1: Inventory
|
|
22
|
+
|
|
23
|
+
#### 1.1 Open Design File
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
mcp__pencil__get_editor_state(include_schema: false)
|
|
27
|
+
mcp__pencil__open_document(filePathOrTemplate: "docs/design.pen")
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### 1.2 List Design Screens
|
|
31
|
+
|
|
32
|
+
Extract top-level frames (screens) from design.pen:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
mcp__pencil__batch_get(
|
|
36
|
+
filePath: "docs/design.pen",
|
|
37
|
+
readDepth: 1
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Filter for screen frames (exclude design system components frame).
|
|
42
|
+
|
|
43
|
+
#### 1.3 List Screen Specifications
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
ls docs/screen/*.md
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Phase 2: Parity Check
|
|
50
|
+
|
|
51
|
+
#### Screen Count Validation
|
|
52
|
+
|
|
53
|
+
| Check | Question |
|
|
54
|
+
| --------------- | ------------------------------------------------------------ |
|
|
55
|
+
| Count match | Does design.pen have same number of screens as screen/\*.md? |
|
|
56
|
+
| Name match | Does each screen in design.pen correspond to a spec file? |
|
|
57
|
+
| Missing screens | Any spec files without corresponding design frames? |
|
|
58
|
+
|
|
59
|
+
Create mapping table:
|
|
60
|
+
|
|
61
|
+
```markdown
|
|
62
|
+
| Screen Spec | Design Frame | Status |
|
|
63
|
+
| ---------------- | -------------------------- | ---------- |
|
|
64
|
+
| {screen-name}.md | {Screen Name} ({frame-id}) | ✅ |
|
|
65
|
+
| {screen-name}.md | - | ❌ Missing |
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Phase 3: Visual Review
|
|
69
|
+
|
|
70
|
+
For each screen, perform detailed review:
|
|
71
|
+
|
|
72
|
+
#### 3.1 Screenshot Capture
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
mcp__pencil__get_screenshot(filePath: "docs/design.pen", nodeId: "{frame-id}")
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### 3.2 Specification Comparison
|
|
79
|
+
|
|
80
|
+
**For ListView screens:**
|
|
81
|
+
|
|
82
|
+
| Check | How to Verify |
|
|
83
|
+
| ---------------------- | ---------------------------------------------------- |
|
|
84
|
+
| Required columns exist | Compare spec table columns with design table headers |
|
|
85
|
+
| Column properties | Sortable/Filterable indicators if applicable |
|
|
86
|
+
| Action buttons | Create/Edit/Delete buttons per spec |
|
|
87
|
+
| Pagination | Present if list can be long |
|
|
88
|
+
|
|
89
|
+
**For Form screens:**
|
|
90
|
+
|
|
91
|
+
| Check | How to Verify |
|
|
92
|
+
| ---------------------- | ------------------------------------------------ |
|
|
93
|
+
| All input fields exist | Match spec field list with form fields |
|
|
94
|
+
| Field types correct | Text/Dropdown/Radio/Checkbox/FileUpload per spec |
|
|
95
|
+
| Required indicators | Required fields marked appropriately |
|
|
96
|
+
| Action buttons | Submit/Cancel buttons present |
|
|
97
|
+
|
|
98
|
+
**For DetailView screens:**
|
|
99
|
+
|
|
100
|
+
| Check | How to Verify |
|
|
101
|
+
| ----------------- | ---------------------------- |
|
|
102
|
+
| Displayed fields | All spec fields visible |
|
|
103
|
+
| Action buttons | Available actions per spec |
|
|
104
|
+
| Status indicators | Badges/Timeline if specified |
|
|
105
|
+
|
|
106
|
+
#### 3.3 Layout Problem Detection
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
mcp__pencil__snapshot_layout(
|
|
110
|
+
filePath: "docs/design.pen",
|
|
111
|
+
parentId: "{frame-id}",
|
|
112
|
+
problemsOnly: true,
|
|
113
|
+
maxDepth: 10
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Common problems:
|
|
118
|
+
|
|
119
|
+
- `partially clipped` - Content overflows container
|
|
120
|
+
- `fully clipped` - Element completely hidden
|
|
121
|
+
- Negative coordinates - Mispositioned elements
|
|
122
|
+
|
|
123
|
+
### Phase 4: Regression Fix
|
|
124
|
+
|
|
125
|
+
#### 4.1 Layout Issues
|
|
126
|
+
|
|
127
|
+
**Fixed height causing overflow:**
|
|
128
|
+
|
|
129
|
+
```javascript
|
|
130
|
+
// Change fixed height to fit_content
|
|
131
|
+
U("{container-id}", { height: "fit_content", justifyContent: "start" });
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Element positioning:**
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// Reset position
|
|
138
|
+
U("{element-id}", { x: 0, y: 0 });
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### 4.2 Style Inconsistencies
|
|
142
|
+
|
|
143
|
+
**Background color mismatch:**
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
// Use design token instead of hardcoded color
|
|
147
|
+
U("{frame-id}", { fill: "$--background" });
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Missing icon:**
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
// Add icon to sidebar item
|
|
154
|
+
U("{frame-id}/{sidebar-id}/{menu-item-id}/{icon-id}", { iconFontName: "{icon-name}" });
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Text not visible (missing fill):**
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
// Add fill color to text
|
|
161
|
+
U("{text-id}", { fill: "$--foreground" });
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
#### 4.3 Missing Fields
|
|
165
|
+
|
|
166
|
+
**Add missing form field:**
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
newField = I("{form-container-id}", {
|
|
170
|
+
type: "ref",
|
|
171
|
+
ref: "{input-component-id}",
|
|
172
|
+
width: "fill_container",
|
|
173
|
+
descendants: {
|
|
174
|
+
"{label-id}": { content: "{field-label}" },
|
|
175
|
+
"{input-id}": { content: "{placeholder}" },
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### 4.4 Common Component Fixes
|
|
181
|
+
|
|
182
|
+
| Issue | Fix Pattern |
|
|
183
|
+
| ----------------------- | ------------------------------------------------ |
|
|
184
|
+
| Card content overflow | Set `height: "fit_content"` on Card Content slot |
|
|
185
|
+
| Sidebar icons missing | Update `iconFontName` on menu item icon element |
|
|
186
|
+
| Text invisible | Add `fill: "$--foreground"` to text element |
|
|
187
|
+
| Inconsistent background | Use `$--background` instead of hex colors |
|
|
188
|
+
|
|
189
|
+
### Phase 5: Validate
|
|
190
|
+
|
|
191
|
+
After fixes, re-verify each screen:
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
mcp__pencil__get_screenshot(filePath: "docs/design.pen", nodeId: "{frame-id}")
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Check:
|
|
198
|
+
|
|
199
|
+
- Layout renders correctly
|
|
200
|
+
- All text visible
|
|
201
|
+
- Consistent styling
|
|
202
|
+
- No clipped elements
|
|
203
|
+
|
|
204
|
+
## Review Report Template
|
|
205
|
+
|
|
206
|
+
```markdown
|
|
207
|
+
## Design Mockup Review Report
|
|
208
|
+
|
|
209
|
+
**Application:** {app-name}
|
|
210
|
+
**Design File:** docs/design.pen
|
|
211
|
+
|
|
212
|
+
### Screen Inventory
|
|
213
|
+
|
|
214
|
+
| Screen | Spec File | Design Frame | Status |
|
|
215
|
+
| ------------- | ---------------- | ------------ | ------ |
|
|
216
|
+
| {screen-name} | {screen-name}.md | {frame-id} | ✅ |
|
|
217
|
+
|
|
218
|
+
### Issues Found & Fixed
|
|
219
|
+
|
|
220
|
+
#### 1. [{screen-name}] - {issue-description}
|
|
221
|
+
|
|
222
|
+
- **Problem:** {description}
|
|
223
|
+
- **Root Cause:** {cause}
|
|
224
|
+
- **Fix Applied:** {fix}
|
|
225
|
+
|
|
226
|
+
### Remaining Issues
|
|
227
|
+
|
|
228
|
+
- [ ] {issue-description}
|
|
229
|
+
|
|
230
|
+
### Summary
|
|
231
|
+
|
|
232
|
+
| Category | Count |
|
|
233
|
+
| ---------------- | ------- |
|
|
234
|
+
| Screens Reviewed | {count} |
|
|
235
|
+
| Issues Found | {count} |
|
|
236
|
+
| Issues Fixed | {count} |
|
|
237
|
+
| Remaining | {count} |
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Design Token Reference
|
|
241
|
+
|
|
242
|
+
Retrieve available design tokens dynamically:
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
mcp__pencil__get_variables(filePath: "docs/design.pen")
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Common token patterns:
|
|
249
|
+
|
|
250
|
+
- `$--background` / `$--foreground` - Base colors
|
|
251
|
+
- `$--card` / `$--border` - Card styling
|
|
252
|
+
- `$--primary` / `$--secondary` - Action colors
|
|
253
|
+
- `$--sidebar-*` - Sidebar-specific tokens
|
|
254
|
+
- `$--muted-*` - Subdued variants
|
|
255
|
+
|
|
256
|
+
## Sidebar Component Reference
|
|
257
|
+
|
|
258
|
+
Retrieve sidebar component structure to find icon element paths:
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
mcp__pencil__batch_get(
|
|
262
|
+
filePath: "docs/design.pen",
|
|
263
|
+
patterns: [{"reusable": true, "name": "Sidebar"}],
|
|
264
|
+
readDepth: 4
|
|
265
|
+
)
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
To find icon names used in an existing screen's sidebar:
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
mcp__pencil__batch_get(
|
|
272
|
+
filePath: "docs/design.pen",
|
|
273
|
+
nodeIds: ["{frame-id}/{sidebar-id}"],
|
|
274
|
+
readDepth: 5,
|
|
275
|
+
resolveInstances: true
|
|
276
|
+
)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Look for `iconFontName` property in sidebar menu items. Icons use Lucide icon font family.
|
|
280
|
+
|
|
281
|
+
## Next Step
|
|
282
|
+
|
|
283
|
+
After completing design review, use `/app-compose-6-implementation-spec` to create Tier 4 documentation (resolvers).
|
|
284
|
+
|
|
285
|
+
## References
|
|
286
|
+
|
|
287
|
+
- [ListView screen](references/screen-listview.md)
|
|
288
|
+
- [Form screen](references/screen-form.md)
|
|
289
|
+
- [DetailView screen](references/screen-detailview.md)
|
|
290
|
+
- [Page components](references/component.md)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Page Components
|
|
2
|
+
|
|
3
|
+
Page-specific components are placed in a `components/` directory, separated from page.tsx.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
{page-name}/
|
|
7
|
+
├── components/
|
|
8
|
+
│ └── *.tsx
|
|
9
|
+
└── page.tsx
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Fragment Collocation
|
|
13
|
+
|
|
14
|
+
Components define and export their own GraphQL Fragment for the data they display. The parent page imports the Fragment and includes it in the query.
|
|
15
|
+
|
|
16
|
+
Use `graphql`, `FragmentOf`, and `readFragment` from `@/graphql`.
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
// components/user-card.tsx
|
|
20
|
+
import { graphql, type FragmentOf, readFragment } from "@/graphql";
|
|
21
|
+
|
|
22
|
+
export const UserCardFragment = graphql(`
|
|
23
|
+
fragment UserCard on User {
|
|
24
|
+
id
|
|
25
|
+
name
|
|
26
|
+
email
|
|
27
|
+
}
|
|
28
|
+
`);
|
|
29
|
+
|
|
30
|
+
export const UserCard = ({ user }: { user: FragmentOf<typeof UserCardFragment> }) => {
|
|
31
|
+
const data = readFragment(UserCardFragment, user);
|
|
32
|
+
return <div>{data.name}</div>;
|
|
33
|
+
};
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
// page.tsx
|
|
38
|
+
import { UserCard, UserCardFragment } from "./components/user-card";
|
|
39
|
+
|
|
40
|
+
const UserQuery = graphql(
|
|
41
|
+
`
|
|
42
|
+
query User($id: ID!) {
|
|
43
|
+
user(id: $id) {
|
|
44
|
+
...UserCard
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
`,
|
|
48
|
+
[UserCardFragment],
|
|
49
|
+
);
|
|
50
|
+
```
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# DetailView Screen Implementation
|
|
2
|
+
|
|
3
|
+
Implementation pattern for screens with `Screen Type: DetailView`.
|
|
4
|
+
Assumes `page.md` and `component.md` rules.
|
|
5
|
+
|
|
6
|
+
## File Structure
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
{screen-path}/[id]/
|
|
10
|
+
├── components/
|
|
11
|
+
│ ├── {screen-name}-detail.tsx # Main content (left column)
|
|
12
|
+
│ └── {screen-name}-actions.tsx # Action sidebar (right column)
|
|
13
|
+
├── edit/
|
|
14
|
+
│ ├── components/
|
|
15
|
+
│ │ └── edit-{screen-name}-form.tsx
|
|
16
|
+
│ └── page.tsx
|
|
17
|
+
└── page.tsx
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Layout
|
|
21
|
+
|
|
22
|
+
- Two-column layout: main content on the left, actions on the right.
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
const ResourcePage = () => {
|
|
26
|
+
const { id } = useParams();
|
|
27
|
+
const [{ data, error, fetching }, reexecuteQuery] = useQuery({
|
|
28
|
+
query: ResourceQuery,
|
|
29
|
+
variables: { id: id! },
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (fetching) return <Loading />;
|
|
33
|
+
if (error || !data?.resource) return <ErrorFallback ... />;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Layout columns={2} title="Resource Detail">
|
|
37
|
+
<Layout.Column>
|
|
38
|
+
<ResourceDetail resource={data.resource} />
|
|
39
|
+
</Layout.Column>
|
|
40
|
+
<Layout.Column>
|
|
41
|
+
<ResourceActions resource={data.resource} />
|
|
42
|
+
</Layout.Column>
|
|
43
|
+
</Layout>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Left Column: Detail Component
|
|
49
|
+
|
|
50
|
+
Stack `DescriptionCard` and related tables vertically with `space-y-6`.
|
|
51
|
+
|
|
52
|
+
- `DescriptionCard` (`@tailor-platform/app-shell`): renders key-value fields declaratively.
|
|
53
|
+
- Complex content (tables, timelines): wrap in `<div className="rounded-lg border bg-card p-6">`.
|
|
54
|
+
|
|
55
|
+
### DescriptionCard
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
<DescriptionCard
|
|
59
|
+
data={resource}
|
|
60
|
+
title="Overview"
|
|
61
|
+
columns={3}
|
|
62
|
+
fields={[
|
|
63
|
+
{ key: "name", label: "Name", meta: { copyable: true } },
|
|
64
|
+
{
|
|
65
|
+
key: "status",
|
|
66
|
+
label: "Status",
|
|
67
|
+
type: "badge",
|
|
68
|
+
meta: { badgeVariantMap: { ACTIVE: "success", PENDING: "warning" } },
|
|
69
|
+
},
|
|
70
|
+
{ type: "divider" },
|
|
71
|
+
{
|
|
72
|
+
key: "createdAt",
|
|
73
|
+
label: "Created At",
|
|
74
|
+
type: "date",
|
|
75
|
+
meta: { dateFormat: "medium" },
|
|
76
|
+
},
|
|
77
|
+
]}
|
|
78
|
+
/>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Field types: `"text"` (default), `"badge"`, `"money"`, `"date"`, `"link"`, `"address"`, `"reference"`, `"divider"`
|
|
82
|
+
|
|
83
|
+
## Right Column: Actions Component
|
|
84
|
+
|
|
85
|
+
Wrap in a `Card` component. Use `Button variant="ghost"` for each action item.
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
<Card>
|
|
89
|
+
<CardHeader>
|
|
90
|
+
<CardTitle>Actions</CardTitle>
|
|
91
|
+
</CardHeader>
|
|
92
|
+
<CardContent className="space-y-2">
|
|
93
|
+
<Button variant="ghost" className="w-full justify-start gap-2" asChild>
|
|
94
|
+
<Link to="edit">✎ Edit</Link>
|
|
95
|
+
</Button>
|
|
96
|
+
<Button variant="ghost" className="w-full justify-start gap-2" onClick={handler}>
|
|
97
|
+
✓ Approve
|
|
98
|
+
</Button>
|
|
99
|
+
</CardContent>
|
|
100
|
+
</Card>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
- Navigation: `<Button variant="ghost" asChild><Link to="...">`
|
|
104
|
+
- Mutation: `<Button variant="ghost" onClick={handler}>` with custom resolvers (see `backend/resolvers.md`)
|
|
105
|
+
- Conditional: show/hide based on status
|
|
106
|
+
- Multiple cards: stack with `<div className="space-y-6">`
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Form Screen Implementation
|
|
2
|
+
|
|
3
|
+
Implementation pattern for screens with `Screen Type: Form`.
|
|
4
|
+
Assumes `page.md` and `component.md` rules.
|
|
5
|
+
|
|
6
|
+
## File Structure
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
{screen-path}/
|
|
10
|
+
├── components/
|
|
11
|
+
│ └── {screen-name}-form.tsx # Form component with validation
|
|
12
|
+
└── page.tsx
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Page Component (page.tsx)
|
|
16
|
+
|
|
17
|
+
Form pages delegate mutation logic to the form component.
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
const ScreenNamePage = () => (
|
|
21
|
+
<Layout columns={1} title="Screen Title">
|
|
22
|
+
<Layout.Column>
|
|
23
|
+
<ScreenNameForm />
|
|
24
|
+
</Layout.Column>
|
|
25
|
+
</Layout>
|
|
26
|
+
);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For edit forms that need existing data, co-locate data fetching in the page component:
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
const EditPage = () => {
|
|
33
|
+
const { id } = useParams();
|
|
34
|
+
const [{ data, error, fetching }] = useQuery({
|
|
35
|
+
query: ResourceQuery,
|
|
36
|
+
variables: { id: id! },
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (fetching) return <Loading />;
|
|
40
|
+
if (error || !data?.resource) return <ErrorFallback ... />;
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Layout columns={1} title="Edit Resource">
|
|
44
|
+
<Layout.Column>
|
|
45
|
+
<EditResourceForm resource={data.resource} />
|
|
46
|
+
</Layout.Column>
|
|
47
|
+
</Layout>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Form Component (components/{screen-name}-form.tsx)
|
|
53
|
+
|
|
54
|
+
### Technology Stack
|
|
55
|
+
|
|
56
|
+
- `react-hook-form` — form state management
|
|
57
|
+
- `zod` + `@hookform/resolvers/zod` — validation
|
|
58
|
+
- `useMutation` (urql) — GraphQL mutation
|
|
59
|
+
- `useNavigate` (@tailor-platform/app-shell) — post-submit navigation
|
|
60
|
+
|
|
61
|
+
### Pattern
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
const formSchema = z.object({
|
|
65
|
+
title: z.string().min(1, "Title is required"),
|
|
66
|
+
description: z.string().optional(),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
type FormValues = z.infer<typeof formSchema>;
|
|
70
|
+
|
|
71
|
+
export const ScreenNameForm = () => {
|
|
72
|
+
const navigate = useNavigate();
|
|
73
|
+
const [, createResource] = useMutation(CreateMutation);
|
|
74
|
+
|
|
75
|
+
const form = useForm<FormValues>({
|
|
76
|
+
resolver: zodResolver(formSchema),
|
|
77
|
+
defaultValues: { title: "", description: "" },
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const onSubmit = (values: FormValues) => {
|
|
81
|
+
void createResource({ input: values }).then((result) => {
|
|
82
|
+
if (!result.error) {
|
|
83
|
+
void navigate("..");
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<Form {...form}>
|
|
90
|
+
<form onSubmit={(e) => void form.handleSubmit(onSubmit)(e)} className="max-w-md space-y-4">
|
|
91
|
+
<FormField
|
|
92
|
+
control={form.control}
|
|
93
|
+
name="title"
|
|
94
|
+
render={({ field }) => (
|
|
95
|
+
<FormItem>
|
|
96
|
+
<FormLabel>Title</FormLabel>
|
|
97
|
+
<FormControl>
|
|
98
|
+
<Input placeholder="Enter title" {...field} />
|
|
99
|
+
</FormControl>
|
|
100
|
+
<FormMessage />
|
|
101
|
+
</FormItem>
|
|
102
|
+
)}
|
|
103
|
+
/>
|
|
104
|
+
<div className="flex gap-2">
|
|
105
|
+
<Button type="submit">Create</Button>
|
|
106
|
+
<Button type="button" variant="outline" onClick={() => void navigate("..")}>
|
|
107
|
+
Cancel
|
|
108
|
+
</Button>
|
|
109
|
+
</div>
|
|
110
|
+
</form>
|
|
111
|
+
</Form>
|
|
112
|
+
);
|
|
113
|
+
};
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Field Type Mapping
|
|
117
|
+
|
|
118
|
+
| Field Type | Component | Zod Schema |
|
|
119
|
+
| ---------- | ------------------------------ | ------------------------------- |
|
|
120
|
+
| Text | `<Input />` | `z.string()` |
|
|
121
|
+
| Textarea | `<textarea className="..." />` | `z.string()` |
|
|
122
|
+
| Dropdown | `<Select />` | `z.string()` or `z.enum([...])` |
|
|
123
|
+
| Date | `<Input type="date" />` | `z.string()` (ISO format) |
|
|
124
|
+
| Number | `<Input type="number" />` | `z.coerce.number()` |
|
|
125
|
+
| Email | `<Input type="email" />` | `z.string().email()` |
|
|
126
|
+
| Checkbox | `<Checkbox />` | `z.boolean()` |
|
|
127
|
+
| Radio | `<RadioGroup />` | `z.enum([...])` |
|
|
128
|
+
|
|
129
|
+
## Validation Mapping
|
|
130
|
+
|
|
131
|
+
- **Required: Yes** → `.min(1, "Field is required")` (string) / `.positive()` (number)
|
|
132
|
+
- **Required: No** → `.optional()`
|
|
133
|
+
|
|
134
|
+
## Key Points
|
|
135
|
+
|
|
136
|
+
- Set `defaultValues` for all fields (empty string, false, etc.)
|
|
137
|
+
- Navigate to `".."` after successful mutation
|
|
138
|
+
- Cancel button must use `type="button"` to prevent form submit
|
|
139
|
+
- For edit forms, accept fragment data as props and pre-fill `defaultValues`
|