devendra-skill-package 1.0.2
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/.github/skills/boiler-project-generator/SKILL.md +103 -0
- package/.github/skills/boiler-project-generator/assets/templates/android/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/angular/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/flutter/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/ios/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/react/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/api-setup.ts +76 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/component-primary-button.tsx +29 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/env-config.env +4 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/feature-auth-screen.tsx +45 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/feature-dashboard-screen.tsx +45 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/feature-profile-screen.tsx +45 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/hook-use-app-boot.ts +11 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/navigation-setup.tsx +25 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/project-structure.md +24 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/redux-hooks.ts +5 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/redux-session-slice.ts +29 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/redux-store.ts +15 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/theme-index.ts +23 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/utils-helpers.ts +7 -0
- package/.github/skills/boiler-project-generator/metadata.yaml +29 -0
- package/.github/skills/boiler-project-generator/references/android.md +19 -0
- package/.github/skills/boiler-project-generator/references/angular.md +14 -0
- package/.github/skills/boiler-project-generator/references/flutter.md +17 -0
- package/.github/skills/boiler-project-generator/references/ios.md +17 -0
- package/.github/skills/boiler-project-generator/references/react-native.md +103 -0
- package/.github/skills/boiler-project-generator/references/react.md +17 -0
- package/.github/skills/boiler-project-generator/scripts/angular.js +43 -0
- package/.github/skills/boiler-project-generator/scripts/generate-project.mjs +107 -0
- package/.github/skills/boiler-project-generator/scripts/init.js +105 -0
- package/.github/skills/boiler-project-generator/scripts/react-native.js +1041 -0
- package/.github/skills/boiler-project-generator/scripts/react.js +32 -0
- package/.github/skills/clean-architecture-generator/SKILL.md +235 -0
- package/.github/skills/clean-architecture-generator/references/architecture-core.md +126 -0
- package/.github/skills/clean-architecture-generator/references/platform-angular.md +374 -0
- package/.github/skills/clean-architecture-generator/references/platform-flutter.md +366 -0
- package/.github/skills/clean-architecture-generator/references/platform-react-native.md +590 -0
- package/.github/skills/clean-architecture-generator/references/platform-react.md +261 -0
- package/.github/skills/code-test-coverage-analyzer/SKILL.md +1358 -0
- package/.github/skills/code-test-coverage-analyzer/assets/config-questionnaire.md +118 -0
- package/.github/skills/code-test-coverage-analyzer/assets/conflict-resolution-protocol.md +99 -0
- package/.github/skills/code-test-coverage-analyzer/assets/coverage-calculation-rules.md +294 -0
- package/.github/skills/code-test-coverage-analyzer/assets/multi-strategy-search.md +145 -0
- package/.github/skills/code-test-coverage-analyzer/assets/output-file-contracts.md +651 -0
- package/.github/skills/code-test-coverage-analyzer/assets/status-definitions.md +273 -0
- package/.github/skills/code-test-coverage-analyzer/examples/example-invocation.md +208 -0
- package/.github/skills/code-test-coverage-analyzer/references/android-patterns.md +229 -0
- package/.github/skills/code-test-coverage-analyzer/references/angular-patterns.md +177 -0
- package/.github/skills/code-test-coverage-analyzer/references/backend-patterns.md +383 -0
- package/.github/skills/code-test-coverage-analyzer/references/flutter-patterns.md +254 -0
- package/.github/skills/code-test-coverage-analyzer/references/ios-patterns.md +228 -0
- package/.github/skills/code-test-coverage-analyzer/references/react-native-patterns.md +431 -0
- package/.github/skills/code-test-coverage-analyzer/references/react-patterns.md +206 -0
- package/.github/skills/code-test-coverage-analyzer/scripts/detect-platform.ps1 +261 -0
- package/.github/skills/code-test-coverage-analyzer/scripts/scan-repository.ps1 +242 -0
- package/.github/skills/code-test-coverage-analyzer/templates/brd-compliance-row.md +107 -0
- package/.github/skills/code-test-coverage-analyzer/templates/test-case-row.md +130 -0
- package/.github/skills/code-test-coverage-analyzer/templates/user-story-compliance-row.md +170 -0
- package/.github/skills/custom-font-integrator/SKILL.md +373 -0
- package/.github/skills/custom-font-integrator/assets/FontTestScreen.js +150 -0
- package/.github/skills/custom-font-integrator/references/example-info-plist.xml +21 -0
- package/.github/skills/custom-font-integrator/scripts/setup-fonts.sh +99 -0
- package/.github/skills/encryption-decryption-utility/Instructions.md +282 -0
- package/.github/skills/encryption-decryption-utility/README.md +222 -0
- package/.github/skills/encryption-decryption-utility/SKILL.md +645 -0
- package/.github/skills/encryption-decryption-utility/assets/encryption-config-template.json +13 -0
- package/.github/skills/encryption-decryption-utility/assets/platform-matrix.json +180 -0
- package/.github/skills/encryption-decryption-utility/metadata.yaml +51 -0
- package/.github/skills/encryption-decryption-utility/references/android-crypto.md +157 -0
- package/.github/skills/encryption-decryption-utility/references/angular-crypto.md +130 -0
- package/.github/skills/encryption-decryption-utility/references/approach-1-webcrypto.md +95 -0
- package/.github/skills/encryption-decryption-utility/references/approach-2-rsa-aes-cbc.md +111 -0
- package/.github/skills/encryption-decryption-utility/references/approach-3-aes-sharedkey.md +114 -0
- package/.github/skills/encryption-decryption-utility/references/architecture.md +233 -0
- package/.github/skills/encryption-decryption-utility/references/backend-alignment.md +506 -0
- package/.github/skills/encryption-decryption-utility/references/dependency-guidance.md +234 -0
- package/.github/skills/encryption-decryption-utility/references/ec-implementation.md +832 -0
- package/.github/skills/encryption-decryption-utility/references/error-handling-playbook.md +234 -0
- package/.github/skills/encryption-decryption-utility/references/flutter-crypto.md +105 -0
- package/.github/skills/encryption-decryption-utility/references/ios-crypto.md +338 -0
- package/.github/skills/encryption-decryption-utility/references/native-rsa-implementation.md +373 -0
- package/.github/skills/encryption-decryption-utility/references/node-crypto.md +86 -0
- package/.github/skills/encryption-decryption-utility/references/react-crypto.md +105 -0
- package/.github/skills/encryption-decryption-utility/references/react-native-crypto.md +1001 -0
- package/.github/skills/encryption-decryption-utility/references/react-web-crypto.md +668 -0
- package/.github/skills/encryption-decryption-utility/references/security-checklist.md +176 -0
- package/.github/skills/encryption-decryption-utility/references/web-crypto.md +74 -0
- package/.github/skills/encryption-decryption-utility/scripts/detect.js +128 -0
- package/.github/skills/encryption-decryption-utility/scripts/install.js +1713 -0
- package/.github/skills/encryption-decryption-utility/scripts/setup.js +800 -0
- package/.github/skills/encryption-decryption-utility/template.md +241 -0
- package/.github/skills/encryption-decryption-utility/templates/config-questionnaire.md +467 -0
- package/.github/skills/encryption-decryption-utility/templates/delivery-checklist.md +206 -0
- package/.github/skills/encryption-decryption-utility/templates/implementation-plan.md +304 -0
- package/.github/skills/feature-generator/SKILL.MD +2741 -0
- package/.github/skills/feature-generator/assets/fingerprint-schema.json +385 -0
- package/.github/skills/feature-generator/assets/spec-template.md +172 -0
- package/.github/skills/feature-generator/assets/transform-rules.json +82 -0
- package/.github/skills/feature-generator/references/api-envelope-patterns.md +327 -0
- package/.github/skills/feature-generator/references/screen-logic-patterns.md +399 -0
- package/.github/skills/feature-generator/references/state-library-patterns.md +464 -0
- package/.github/skills/figma-ui-mapper/README.md +34 -0
- package/.github/skills/figma-ui-mapper/SKILL.md +101 -0
- package/.github/skills/figma-ui-mapper/assets/templates/component-map-template.md +30 -0
- package/.github/skills/figma-ui-mapper/assets/templates/generation-report-template.md +49 -0
- package/.github/skills/figma-ui-mapper/metadata.yaml +22 -0
- package/.github/skills/figma-ui-mapper/references/android.md +11 -0
- package/.github/skills/figma-ui-mapper/references/angular.md +18 -0
- package/.github/skills/figma-ui-mapper/references/capacitor.md +18 -0
- package/.github/skills/figma-ui-mapper/references/common.md +23 -0
- package/.github/skills/figma-ui-mapper/references/expo.md +18 -0
- package/.github/skills/figma-ui-mapper/references/flutter.md +18 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/angular/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/capacitor/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/expo/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/flutter/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/ionic/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/kotlin-multiplatform/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/native-android/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/native-ios/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/next/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/nuxt/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/react/rules.md +19 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/react-native/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/svelte/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/vue/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/ionic.md +18 -0
- package/.github/skills/figma-ui-mapper/references/ios.md +11 -0
- package/.github/skills/figma-ui-mapper/references/kotlin-multiplatform.md +18 -0
- package/.github/skills/figma-ui-mapper/references/native-android.md +18 -0
- package/.github/skills/figma-ui-mapper/references/native-ios.md +18 -0
- package/.github/skills/figma-ui-mapper/references/next.md +18 -0
- package/.github/skills/figma-ui-mapper/references/nuxt.md +18 -0
- package/.github/skills/figma-ui-mapper/references/react-figma-guideline.md +21 -0
- package/.github/skills/figma-ui-mapper/references/react-native.md +18 -0
- package/.github/skills/figma-ui-mapper/references/react.md +18 -0
- package/.github/skills/figma-ui-mapper/references/script-usage.md +46 -0
- package/.github/skills/figma-ui-mapper/references/svelte.md +18 -0
- package/.github/skills/figma-ui-mapper/references/vue.md +18 -0
- package/.github/skills/figma-ui-mapper/references/workflow.md +74 -0
- package/.github/skills/figma-ui-mapper/scripts/generate-page-through-figma.js +635 -0
- package/.github/skills/figma-ui-mapper/scripts/generate-react-page-through-figma.js +4 -0
- package/.github/skills/frontend-task-breakdown/SKILL.md +734 -0
- package/.github/skills/md-file-converter/SKILL.md +291 -0
- package/.github/skills/md-file-converter/config/formats.json +114 -0
- package/.github/skills/md-file-converter/extractors/extract-docx.sh +120 -0
- package/.github/skills/md-file-converter/extractors/extract-eml.py +108 -0
- package/.github/skills/md-file-converter/extractors/extract-pdf.sh +97 -0
- package/.github/skills/md-file-converter/extractors/extract-pptx.py +143 -0
- package/.github/skills/md-file-converter/extractors/extract-xlsx.py +175 -0
- package/.github/skills/md-file-converter/scripts/check-tools.sh +47 -0
- package/.github/skills/md-file-converter/scripts/extract-archive.sh +83 -0
- package/.github/skills/md-file-converter/scripts/extract-ocr.sh +77 -0
- package/.github/skills/md-file-converter/scripts/get-metadata.sh +57 -0
- package/.github/skills/md-file-converter/templates/output.md +73 -0
- package/.github/skills/md-file-converter/templates/unsupported-object.md +6 -0
- package/.github/skills/mockAPI-contract-generator/SKILL.md +607 -0
- package/.github/skills/test-case-validator/CHANGELOG.md +155 -0
- package/.github/skills/test-case-validator/CONFIGURATION.md +130 -0
- package/.github/skills/test-case-validator/EXAMPLES.md +50 -0
- package/.github/skills/test-case-validator/QUALITY_SCORING.md +98 -0
- package/.github/skills/test-case-validator/README.md +111 -0
- package/.github/skills/test-case-validator/REPORT_TEMPLATE.md +116 -0
- package/.github/skills/test-case-validator/SKILL.md +209 -0
- package/.github/skills/test-case-validator/SYSTEM_PROMPT.md +127 -0
- package/.github/skills/test-case-validator/TRACEABILITY_ENGINE.md +152 -0
- package/.github/skills/test-case-validator/VALIDATION_RULES.md +411 -0
- package/.github/skills/test-case-validator/config/default.config.yaml +62 -0
- package/.github/skills/test-case-validator/docs/ARCHITECTURE.md +66 -0
- package/.github/skills/test-case-validator/docs/EXTENDING.md +85 -0
- package/.github/skills/test-case-validator/docs/FAQ.md +88 -0
- package/.github/skills/test-case-validator/docs/VERSIONING.md +55 -0
- package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/input-brd.md +43 -0
- package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/input-test-cases.csv +9 -0
- package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/input-user-story.md +29 -0
- package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/output-report.md +303 -0
- package/.github/skills/test-case-validator/examples/example-2-automated-frontend-suite/input-spec.md +43 -0
- package/.github/skills/test-case-validator/examples/example-2-automated-frontend-suite/input-test-files-index.md +56 -0
- package/.github/skills/test-case-validator/examples/example-2-automated-frontend-suite/output-report.md +274 -0
- package/.github/skills/test-case-validator/prompts/00-applicability-resolution.md +61 -0
- package/.github/skills/test-case-validator/prompts/01-extraction-user-story.md +58 -0
- package/.github/skills/test-case-validator/prompts/02-extraction-brd.md +64 -0
- package/.github/skills/test-case-validator/prompts/03-extraction-test-cases.md +92 -0
- package/.github/skills/test-case-validator/prompts/04-traceability-matrix.md +41 -0
- package/.github/skills/test-case-validator/prompts/05-coverage-analysis.md +46 -0
- package/.github/skills/test-case-validator/prompts/06-missing-scenario-detection.md +32 -0
- package/.github/skills/test-case-validator/prompts/07-duplicate-detection.md +36 -0
- package/.github/skills/test-case-validator/prompts/08-risk-analysis.md +39 -0
- package/.github/skills/test-case-validator/prompts/09-gated-wiring-validation.md +53 -0
- package/.github/skills/test-case-validator/prompts/10-observation-report.md +56 -0
- package/.github/skills/test-case-validator/prompts/11-final-report-assembly.md +57 -0
- package/.github/skills/test-case-validator/templates/coverage-table.md +25 -0
- package/.github/skills/test-case-validator/templates/executive-summary.md +38 -0
- package/.github/skills/test-case-validator/templates/final-summary-block.md +87 -0
- package/.github/skills/test-case-validator/templates/observation-entry.md +41 -0
- package/.github/skills/test-case-validator/templates/rtm-row.md +25 -0
- package/.github/skills/validation-engine-builder/README.md +50 -0
- package/.github/skills/validation-engine-builder/SKILL.md +241 -0
- package/.github/skills/validation-engine-builder/references/core.md +158 -0
- package/.github/skills/validation-engine-builder/references/platform-angular.md +166 -0
- package/.github/skills/validation-engine-builder/references/platform-flutter.md +118 -0
- package/.github/skills/validation-engine-builder/references/platform-react-native.md +170 -0
- package/.github/skills/validation-engine-builder/references/platform-react.md +94 -0
- package/.github/skills/validation-engine-builder/scripts/apply-to-project.js +80 -0
- package/.github/skills/validation-engine-builder/scripts/generate-angular.js +271 -0
- package/.github/skills/validation-engine-builder/scripts/generate-flutter.js +298 -0
- package/.github/skills/validation-engine-builder/scripts/generate-react-native.js +217 -0
- package/.github/skills/validation-engine-builder/scripts/generate-react.js +163 -0
- package/.github/skills/validation-engine-builder/scripts/install-deps.js +53 -0
- package/.github/skills/validation-engine-builder/scripts/shared/detect-platform.js +68 -0
- package/.github/skills/validation-engine-builder/scripts/shared/npm-deps.js +103 -0
- package/.github/skills/validation-engine-builder/scripts/shared/rhf-hook.js +43 -0
- package/.github/skills/validation-engine-builder/scripts/shared/ts-messages-regex.js +62 -0
- package/.github/skills/validation-engine-builder/scripts/shared/util.js +44 -0
- package/.github/skills/validation-engine-builder/scripts/shared/yup-schemas.js +80 -0
- package/.github/skills/validation-engine-builder/template.md +73 -0
- package/.github/skills/validation-engine-builder/templates/messages.json +22 -0
- package/.github/skills/validation-engine-builder/templates/regex.json +16 -0
- package/.github/skills/validation-engine-builder/templates/schemas.json +48 -0
- package/bin/index.js +145 -0
- package/package.json +22 -0
- package/readme.md +0 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
# Screen Logic Patterns Reference
|
|
2
|
+
|
|
3
|
+
Used by Phase 7.3 of feature-generator.
|
|
4
|
+
Each pattern below corresponds to a phrase in the spec `Screen Logic` section.
|
|
5
|
+
Patterns are combined in the screen component — they are not mutually exclusive.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Pattern: Fetch on screen mount
|
|
10
|
+
|
|
11
|
+
**Spec phrase**: "Fetch data on screen mount", "Load data when screen opens"
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
const dispatch = useDispatch<AppDispatch>();
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
dispatch(fetch<ScreenName>Thunk({ clientCode, sessionId }));
|
|
18
|
+
}, [dispatch, clientCode, sessionId]);
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**For Zustand:**
|
|
22
|
+
```typescript
|
|
23
|
+
const fetch<ScreenName> = use<ScreenName>Store((state) => state.fetch<ScreenName>);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
void fetch<ScreenName>({ clientCode, sessionId });
|
|
27
|
+
}, [fetch<ScreenName>, clientCode, sessionId]);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**For React Query / RTK Query:**
|
|
31
|
+
```typescript
|
|
32
|
+
// No useEffect needed — the query hook fetches automatically on mount
|
|
33
|
+
const { data, isLoading, error, refetch } = use<ScreenName>({ clientCode, sessionId });
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Pattern: Pull to refresh
|
|
39
|
+
|
|
40
|
+
**Spec phrase**: "Support pull-to-refresh", "Refresh on pull"
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
// State
|
|
44
|
+
const isRefreshing = useSelector(select<ScreenName>IsRefreshing);
|
|
45
|
+
|
|
46
|
+
const handleRefresh = useCallback(() => {
|
|
47
|
+
dispatch(refresh<ScreenName>Thunk({ clientCode, sessionId }));
|
|
48
|
+
}, [dispatch, clientCode, sessionId]);
|
|
49
|
+
|
|
50
|
+
// JSX — add to FlatList or ScrollView
|
|
51
|
+
<FlatList
|
|
52
|
+
data={items}
|
|
53
|
+
refreshControl={
|
|
54
|
+
<RefreshControl
|
|
55
|
+
refreshing={isRefreshing}
|
|
56
|
+
onRefresh={handleRefresh}
|
|
57
|
+
tintColor="#02168b"
|
|
58
|
+
colors={['#02168b']}
|
|
59
|
+
/>
|
|
60
|
+
}
|
|
61
|
+
// ...
|
|
62
|
+
/>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Notes:**
|
|
66
|
+
- The `refresh<ScreenName>Thunk` sets `isRefreshing` (not `isLoading`) in the slice.
|
|
67
|
+
- The thunk body is identical to `fetch<ScreenName>Thunk` — only the pending handler differs.
|
|
68
|
+
- If the state lib has no separate refresh thunk (Zustand, Context, MobX), use a
|
|
69
|
+
local boolean state for `isRefreshing` and call the same fetch action.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Pattern: Navigate to detail on tap
|
|
74
|
+
|
|
75
|
+
**Spec phrase**: "Navigate to DetailScreen when user taps a row",
|
|
76
|
+
"Tap a row to open detail"
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// For react-navigation (fingerprint.navLib = "react-navigation")
|
|
80
|
+
import { useNavigation } from '@react-navigation/native';
|
|
81
|
+
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
|
82
|
+
import type { <NavParamsPattern> } from '<relative-path-to-routes>';
|
|
83
|
+
|
|
84
|
+
type NavProp = NativeStackNavigationProp<<NavParamsPattern>>;
|
|
85
|
+
|
|
86
|
+
// Inside component:
|
|
87
|
+
const navigation = useNavigation<NavProp>();
|
|
88
|
+
|
|
89
|
+
const handleItemPress = useCallback((item: <ScreenName>Item) => {
|
|
90
|
+
navigation.navigate('<TargetScreenName>', { itemId: item.id });
|
|
91
|
+
}, [navigation]);
|
|
92
|
+
|
|
93
|
+
// In FlatList renderItem:
|
|
94
|
+
<Pressable onPress={() => handleItemPress(item)}>
|
|
95
|
+
{/* row content */}
|
|
96
|
+
</Pressable>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// For expo-router (fingerprint.navLib = "expo-router")
|
|
101
|
+
import { useRouter } from 'expo-router';
|
|
102
|
+
|
|
103
|
+
const router = useRouter();
|
|
104
|
+
|
|
105
|
+
const handleItemPress = useCallback((item: <ScreenName>Item) => {
|
|
106
|
+
router.push({ pathname: '/<featureName>/[id]', params: { id: item.id } });
|
|
107
|
+
}, [router]);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Notes:**
|
|
111
|
+
- The target screen name and params come from the spec screenLogic description.
|
|
112
|
+
If not specified, use `<ScreenName>DetailScreen` and pass `itemId`.
|
|
113
|
+
- Add a TODO comment if the target screen does not yet exist.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Pattern: Empty state
|
|
118
|
+
|
|
119
|
+
**Spec phrase**: "Show empty state when list is empty",
|
|
120
|
+
"Display 'No items found' message"
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// Derive in component:
|
|
124
|
+
const isEmpty = !isLoading && items.length === 0;
|
|
125
|
+
|
|
126
|
+
// In FlatList:
|
|
127
|
+
<FlatList
|
|
128
|
+
data={items}
|
|
129
|
+
ListEmptyComponent={
|
|
130
|
+
isEmpty ? (
|
|
131
|
+
<View style={styles.emptyContainer}>
|
|
132
|
+
<Text style={styles.emptyText}>
|
|
133
|
+
{/* Use exact message from spec, or default below */}
|
|
134
|
+
No items found
|
|
135
|
+
</Text>
|
|
136
|
+
</View>
|
|
137
|
+
) : null
|
|
138
|
+
}
|
|
139
|
+
// ...
|
|
140
|
+
/>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Styles:**
|
|
144
|
+
```typescript
|
|
145
|
+
emptyContainer: {
|
|
146
|
+
flex: 1,
|
|
147
|
+
alignItems: 'center',
|
|
148
|
+
justifyContent: 'center',
|
|
149
|
+
paddingVertical: 64,
|
|
150
|
+
},
|
|
151
|
+
emptyText: {
|
|
152
|
+
fontSize: 14,
|
|
153
|
+
color: '#71789d',
|
|
154
|
+
textAlign: 'center',
|
|
155
|
+
},
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Pattern: Loading skeleton / loading state
|
|
161
|
+
|
|
162
|
+
**Spec phrase**: "Show loading skeleton while fetching", "Loading indicator",
|
|
163
|
+
"Show shimmer placeholder"
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
const isLoading = useSelector(select<ScreenName>IsLoading);
|
|
167
|
+
|
|
168
|
+
if (isLoading) {
|
|
169
|
+
return (
|
|
170
|
+
<View style={styles.loadingContainer}>
|
|
171
|
+
{/* If a Skeleton component exists in the project, use it. Otherwise use ActivityIndicator. */}
|
|
172
|
+
<ActivityIndicator size="large" color="#02168b" />
|
|
173
|
+
</View>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Notes:**
|
|
179
|
+
- Detect whether the project has a custom Skeleton/Shimmer component
|
|
180
|
+
by scanning the `presentation/components/` folder. If found, use it.
|
|
181
|
+
- Do NOT use `<ActivityIndicator>` if a Skeleton component is already present —
|
|
182
|
+
use the existing pattern for visual consistency.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Pattern: Error state
|
|
187
|
+
|
|
188
|
+
**Spec phrase**: "Show error message if fetch fails", "Display error state"
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
const error = useSelector(select<ScreenName>Error);
|
|
192
|
+
const isLoading = useSelector(select<ScreenName>IsLoading);
|
|
193
|
+
|
|
194
|
+
// Define handleRefetch alongside the initial fetch dispatch
|
|
195
|
+
const handleRefetch = useCallback(() => {
|
|
196
|
+
dispatch(fetch<ScreenName>Thunk({ clientCode, sessionId }));
|
|
197
|
+
}, [dispatch, clientCode, sessionId]);
|
|
198
|
+
|
|
199
|
+
if (error !== null && !isLoading) {
|
|
200
|
+
return (
|
|
201
|
+
<View style={styles.errorContainer}>
|
|
202
|
+
<Text style={styles.errorText}>{error}</Text>
|
|
203
|
+
<Pressable onPress={handleRefetch} style={styles.retryButton}>
|
|
204
|
+
<Text style={styles.retryButtonText}>Retry</Text>
|
|
205
|
+
</Pressable>
|
|
206
|
+
</View>
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Pattern: Auth error + logout
|
|
214
|
+
|
|
215
|
+
**Spec phrase**: "Display auth error and logout button if session expires",
|
|
216
|
+
"Handle 401 / session expiry"
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
const isAuthError = useSelector(select<ScreenName>IsAuthError);
|
|
220
|
+
|
|
221
|
+
if (isAuthError) {
|
|
222
|
+
return (
|
|
223
|
+
<View style={styles.errorContainer}>
|
|
224
|
+
<Text style={styles.errorText}>Your session has expired. Please log in again.</Text>
|
|
225
|
+
<Pressable
|
|
226
|
+
onPress={() => {
|
|
227
|
+
// Navigate to login. Use detected nav pattern.
|
|
228
|
+
navigation.reset({ index: 0, routes: [{ name: 'Login' }] });
|
|
229
|
+
}}
|
|
230
|
+
style={styles.retryButton}
|
|
231
|
+
>
|
|
232
|
+
<Text style={styles.retryButtonText}>Log In Again</Text>
|
|
233
|
+
</Pressable>
|
|
234
|
+
</View>
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Pattern: Tab switcher
|
|
242
|
+
|
|
243
|
+
**Spec phrase**: "Tab bar to switch between views", "Filter by tab",
|
|
244
|
+
"Tab switcher between Asset classes"
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
// State (added to slice or local state)
|
|
248
|
+
const [activeTab, setActiveTab] = useState('<first tab value from spec>');
|
|
249
|
+
|
|
250
|
+
// Derived data
|
|
251
|
+
const filteredItems = useMemo(
|
|
252
|
+
() => items.filter((item) => item.category === activeTab || activeTab === 'All'),
|
|
253
|
+
[items, activeTab],
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
// JSX — horizontal scrollable tab bar
|
|
257
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.tabBar}>
|
|
258
|
+
{tabOptions.map((tab) => (
|
|
259
|
+
<Pressable
|
|
260
|
+
key={tab}
|
|
261
|
+
onPress={() => setActiveTab(tab)}
|
|
262
|
+
style={[styles.tab, activeTab === tab && styles.tabActive]}
|
|
263
|
+
>
|
|
264
|
+
<Text style={[styles.tabText, activeTab === tab && styles.tabTextActive]}>
|
|
265
|
+
{tab}
|
|
266
|
+
</Text>
|
|
267
|
+
</Pressable>
|
|
268
|
+
))}
|
|
269
|
+
</ScrollView>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Pattern: Filter list (search/query)
|
|
275
|
+
|
|
276
|
+
**Spec phrase**: "Filter list by search query", "Search functionality"
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
// State
|
|
280
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
281
|
+
|
|
282
|
+
// Derived
|
|
283
|
+
const filteredItems = useMemo(
|
|
284
|
+
() =>
|
|
285
|
+
searchQuery.trim() === ''
|
|
286
|
+
? items
|
|
287
|
+
: items.filter((item) =>
|
|
288
|
+
item.name.toLowerCase().includes(searchQuery.toLowerCase()),
|
|
289
|
+
),
|
|
290
|
+
[items, searchQuery],
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
// JSX
|
|
294
|
+
<TextInput
|
|
295
|
+
value={searchQuery}
|
|
296
|
+
onChangeText={setSearchQuery}
|
|
297
|
+
placeholder="Search..."
|
|
298
|
+
style={styles.searchInput}
|
|
299
|
+
/>
|
|
300
|
+
<FlatList data={filteredItems} /* ... */ />
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Pattern: Summary card at top of list
|
|
306
|
+
|
|
307
|
+
**Spec phrase**: "Summary card at the top", "Header card with totals"
|
|
308
|
+
|
|
309
|
+
Use `ListHeaderComponent` on FlatList — never render the header above FlatList
|
|
310
|
+
as a sibling view when the list scrolls, to avoid nested scroll issues.
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
const SummaryCard = useMemo(() => (
|
|
314
|
+
<View style={styles.summaryCard}>
|
|
315
|
+
{/* map spec responseMappings that are not list-row fields */}
|
|
316
|
+
<Text style={styles.summaryLabel}>Total Value</Text>
|
|
317
|
+
<Text style={styles.summaryValue}>{totalValue}</Text>
|
|
318
|
+
</View>
|
|
319
|
+
), [totalValue]);
|
|
320
|
+
|
|
321
|
+
<FlatList
|
|
322
|
+
data={items}
|
|
323
|
+
ListHeaderComponent={SummaryCard}
|
|
324
|
+
// ...
|
|
325
|
+
/>
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Pattern: Pagination / load more
|
|
331
|
+
|
|
332
|
+
**Spec phrase**: "Pagination", "Load more on scroll end", "Infinite scroll"
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
// State
|
|
336
|
+
const [page, setPage] = useState(1);
|
|
337
|
+
const hasMore = useSelector(select<ScreenName>HasMore);
|
|
338
|
+
|
|
339
|
+
const handleEndReached = useCallback(() => {
|
|
340
|
+
if (!isLoading && hasMore) {
|
|
341
|
+
const nextPage = page + 1;
|
|
342
|
+
setPage(nextPage);
|
|
343
|
+
dispatch(fetch<ScreenName>PageThunk({ clientCode, sessionId, page: nextPage }));
|
|
344
|
+
}
|
|
345
|
+
}, [dispatch, isLoading, hasMore, page, clientCode, sessionId]);
|
|
346
|
+
|
|
347
|
+
<FlatList
|
|
348
|
+
data={items}
|
|
349
|
+
onEndReached={handleEndReached}
|
|
350
|
+
onEndReachedThreshold={0.3}
|
|
351
|
+
ListFooterComponent={isLoading && page > 1 ? <ActivityIndicator /> : null}
|
|
352
|
+
// ...
|
|
353
|
+
/>
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## FlatList scaffold (base template — all list screens)
|
|
359
|
+
|
|
360
|
+
Combine patterns above by composing into this base FlatList structure:
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
<FlatList
|
|
364
|
+
data={filteredItems}
|
|
365
|
+
keyExtractor={(item) => String(item.<idField>)}
|
|
366
|
+
renderItem={({ item }) => (
|
|
367
|
+
<Pressable onPress={() => handleItemPress(item)}>
|
|
368
|
+
{/* Row content using responseMappings */}
|
|
369
|
+
</Pressable>
|
|
370
|
+
)}
|
|
371
|
+
ListHeaderComponent={<SummaryCard />} // if "summary card" in spec
|
|
372
|
+
ListEmptyComponent={<EmptyState />} // if "empty state" in spec
|
|
373
|
+
ListFooterComponent={<FooterLoader />} // if "pagination" in spec
|
|
374
|
+
refreshControl={<RefreshControl ... />} // if "pull to refresh" in spec
|
|
375
|
+
showsVerticalScrollIndicator={false}
|
|
376
|
+
contentContainerStyle={styles.listContent}
|
|
377
|
+
/>
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Screen file structure (always follow this order)
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
// 1. React imports
|
|
386
|
+
// 2. React Native imports
|
|
387
|
+
// 3. Third-party library imports (react-redux, react-navigation, etc.)
|
|
388
|
+
// 4. Feature-local imports (state, selectors, thunks)
|
|
389
|
+
// 5. Shared imports (assets, design tokens, shared components)
|
|
390
|
+
// 6. Type-only imports (import type {...})
|
|
391
|
+
|
|
392
|
+
// Component function
|
|
393
|
+
// ---- hooks (useSelector, useDispatch, useCallback, useEffect) ----
|
|
394
|
+
// ---- derived values (useMemo) ----
|
|
395
|
+
// ---- conditional early returns (loading, auth error, error) ----
|
|
396
|
+
// ---- main render ----
|
|
397
|
+
|
|
398
|
+
// StyleSheet.create() — always at bottom of file
|
|
399
|
+
```
|