rnsup 1.0.2 → 1.0.3
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/README.md +139 -229
- package/dist/commands/generateComponent.js +38 -24
- package/dist/commands/generateFolder.js +2 -1
- package/dist/commands/generateScreen.js +35 -10
- package/dist/commands/setup.js +1 -1
- package/dist/commands/viewStructure.js +91 -0
- package/dist/index.js +9 -0
- package/dist/templates/componentTemplates.js +99 -0
- package/dist/templates/screenTemplates.js +342 -0
- package/dist/utils/selectPrompt.js +13 -24
- package/dist/utils/treeGenerator.js +170 -0
- package/package.json +2 -2
package/dist/commands/setup.js
CHANGED
|
@@ -35,7 +35,7 @@ async function runSetup() {
|
|
|
35
35
|
process.exit(1);
|
|
36
36
|
}
|
|
37
37
|
/* ---------- 2. Ask package manager ---------- */
|
|
38
|
-
const manager = await (0, selectPrompt_1.selectOption)('Which package manager do you want to use?', ['npm', 'yarn', 'pnpm']);
|
|
38
|
+
const manager = await (0, selectPrompt_1.selectOption)('Which package manager do you want to use?', ['npm', 'yarn', 'pnpm'], 'yarn');
|
|
39
39
|
/* ---------- 3. Validate manager installed ---------- */
|
|
40
40
|
if (!(0, packageManager_1.isInstalled)(manager)) {
|
|
41
41
|
console.log('\nSelected package manager is not installed on your system.\n');
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.viewStructure = viewStructure;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
|
+
const treeGenerator_1 = require("../utils/treeGenerator");
|
|
11
|
+
const handleCancel_1 = require("../utils/handleCancel");
|
|
12
|
+
async function viewStructure(options) {
|
|
13
|
+
try {
|
|
14
|
+
// Handle Ctrl+C gracefully
|
|
15
|
+
process.on('SIGINT', () => {
|
|
16
|
+
console.log(chalk_1.default.yellow('\n\nCancelled.'));
|
|
17
|
+
process.exit(0);
|
|
18
|
+
});
|
|
19
|
+
// Parse flags
|
|
20
|
+
const pretty = options.pretty || options.p || false;
|
|
21
|
+
const showTime = options.time || false;
|
|
22
|
+
// Show hints if first time or no input
|
|
23
|
+
if (!options.parent?.args?.[1]) {
|
|
24
|
+
console.log('\n' + chalk_1.default.cyan.bold('💡 Usage Hints'));
|
|
25
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
26
|
+
console.log(chalk_1.default.yellow('Command:'), chalk_1.default.white('rnsup view [options]'));
|
|
27
|
+
console.log();
|
|
28
|
+
console.log(chalk_1.default.yellow('Input options (when prompted):'));
|
|
29
|
+
console.log(' ' + chalk_1.default.white('. or root') + chalk_1.default.gray(' → Show entire project (all folders/files)'));
|
|
30
|
+
console.log(' ' + chalk_1.default.white('src') + chalk_1.default.gray(' → Show only src/ directory'));
|
|
31
|
+
console.log();
|
|
32
|
+
console.log(chalk_1.default.yellow('Command flags:'));
|
|
33
|
+
console.log(' ' + chalk_1.default.white('-p, --pretty') + chalk_1.default.gray(' → Show with icons, colors, and file sizes'));
|
|
34
|
+
console.log(' ' + chalk_1.default.white('--time') + chalk_1.default.gray(' → Show file/folder creation date and time'));
|
|
35
|
+
console.log();
|
|
36
|
+
console.log(chalk_1.default.yellow('Examples:'));
|
|
37
|
+
console.log(' ' + chalk_1.default.white('rnsup view') + chalk_1.default.gray(' → Raw structure (no icons)'));
|
|
38
|
+
console.log(' ' + chalk_1.default.white('rnsup view -p') + chalk_1.default.gray(' → Pretty view with icons & colors'));
|
|
39
|
+
console.log(' ' + chalk_1.default.white('rnsup view --time') + chalk_1.default.gray(' → Show with timestamps'));
|
|
40
|
+
console.log(' ' + chalk_1.default.white('rnsup view -p --time') + chalk_1.default.gray(' → Pretty view + timestamps'));
|
|
41
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
42
|
+
console.log();
|
|
43
|
+
}
|
|
44
|
+
const { viewTarget } = await inquirer_1.default.prompt([
|
|
45
|
+
{
|
|
46
|
+
type: 'list',
|
|
47
|
+
name: 'viewTarget',
|
|
48
|
+
message: 'What would you like to view?',
|
|
49
|
+
choices: [
|
|
50
|
+
{ name: '📂 Root level (entire project)', value: 'root' },
|
|
51
|
+
{ name: '📂 Inside src/ folder only', value: 'src' }
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
]);
|
|
55
|
+
let targetPath = process.cwd();
|
|
56
|
+
let displayLocation = 'root';
|
|
57
|
+
if (viewTarget === 'src') {
|
|
58
|
+
targetPath = path_1.default.join(process.cwd(), 'src');
|
|
59
|
+
displayLocation = 'src';
|
|
60
|
+
}
|
|
61
|
+
// Show colored header
|
|
62
|
+
console.log('\n' + chalk_1.default.cyan.bold('📋 Directory Structure'));
|
|
63
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
64
|
+
console.log(chalk_1.default.yellow('Location: '), chalk_1.default.white(displayLocation));
|
|
65
|
+
console.log(chalk_1.default.yellow('Mode: '), pretty ? chalk_1.default.magenta('Pretty') : chalk_1.default.dim('Raw'));
|
|
66
|
+
if (showTime) {
|
|
67
|
+
console.log(chalk_1.default.yellow('Time: '), chalk_1.default.magenta('Enabled'));
|
|
68
|
+
}
|
|
69
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
70
|
+
console.log();
|
|
71
|
+
// Build and display tree
|
|
72
|
+
const nodes = await (0, treeGenerator_1.buildTree)(targetPath, 10);
|
|
73
|
+
if (nodes.length === 0) {
|
|
74
|
+
console.log(chalk_1.default.yellow('No files or folders found in this directory.'));
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const formattedTree = (0, treeGenerator_1.formatTree)(nodes, { pretty, showTime });
|
|
78
|
+
console.log(formattedTree);
|
|
79
|
+
}
|
|
80
|
+
// Footer with hints
|
|
81
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
82
|
+
if (pretty) {
|
|
83
|
+
console.log(chalk_1.default.dim('📁 Cyan = folders | Colors = file types (blue=.ts, green=.json, etc)'));
|
|
84
|
+
}
|
|
85
|
+
console.log(chalk_1.default.dim('💡 Tip: You can copy the structure above for documentation'));
|
|
86
|
+
console.log();
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
(0, handleCancel_1.handleCancel)(err);
|
|
90
|
+
}
|
|
91
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const setup_1 = require("./commands/setup");
|
|
|
5
5
|
const generateScreen_1 = require("./commands/generateScreen");
|
|
6
6
|
const generateComponent_1 = require("./commands/generateComponent");
|
|
7
7
|
const generateFolder_1 = require("./commands/generateFolder");
|
|
8
|
+
const viewStructure_1 = require("./commands/viewStructure");
|
|
8
9
|
const program = new commander_1.Command();
|
|
9
10
|
program
|
|
10
11
|
.name('rnsup')
|
|
@@ -15,6 +16,14 @@ program
|
|
|
15
16
|
.command('setup')
|
|
16
17
|
.description('Configure React Native project')
|
|
17
18
|
.action(setup_1.runSetup);
|
|
19
|
+
/* ---------- View Structure ---------- */
|
|
20
|
+
program
|
|
21
|
+
.command('view')
|
|
22
|
+
.alias('v')
|
|
23
|
+
.description('View project folder structure')
|
|
24
|
+
.option('-p, --pretty', 'Show with icons, colors and file sizes')
|
|
25
|
+
.option('--time', 'Show file/folder creation date and time')
|
|
26
|
+
.action(viewStructure_1.viewStructure);
|
|
18
27
|
/* ---------- Generator Root ---------- */
|
|
19
28
|
const generate = new commander_1.Command('generate')
|
|
20
29
|
.alias('g')
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getComponentTemplate = getComponentTemplate;
|
|
4
|
+
function getComponentTemplate(name, type) {
|
|
5
|
+
switch (type) {
|
|
6
|
+
case 'container':
|
|
7
|
+
return containerComponentTemplate(name);
|
|
8
|
+
default:
|
|
9
|
+
return presentationalComponentTemplate(name);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function presentationalComponentTemplate(name) {
|
|
13
|
+
return `import React from 'react';
|
|
14
|
+
import { View, Text, StyleSheet, ViewStyle, TextStyle } from 'react-native';
|
|
15
|
+
|
|
16
|
+
interface Props {
|
|
17
|
+
title?: string;
|
|
18
|
+
children?: React.ReactNode;
|
|
19
|
+
style?: ViewStyle;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const ${name}: React.FC<Props> = ({ title, children, style }) => {
|
|
23
|
+
return (
|
|
24
|
+
<View style={[styles.container, style]}>
|
|
25
|
+
{title && <Text style={styles.title}>{title}</Text>}
|
|
26
|
+
{children}
|
|
27
|
+
</View>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default ${name};
|
|
32
|
+
|
|
33
|
+
const styles = StyleSheet.create({
|
|
34
|
+
container: {
|
|
35
|
+
paddingHorizontal: 16,
|
|
36
|
+
paddingVertical: 12,
|
|
37
|
+
},
|
|
38
|
+
title: {
|
|
39
|
+
fontSize: 16,
|
|
40
|
+
fontWeight: '600',
|
|
41
|
+
marginBottom: 8,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
function containerComponentTemplate(name) {
|
|
47
|
+
return `import React, { useState } from 'react';
|
|
48
|
+
import { View, StyleSheet, ViewStyle } from 'react-native';
|
|
49
|
+
import { useNavigation } from '@react-navigation/native';
|
|
50
|
+
|
|
51
|
+
interface Props {
|
|
52
|
+
style?: ViewStyle;
|
|
53
|
+
children?: React.ReactNode;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface State {
|
|
57
|
+
loading: boolean;
|
|
58
|
+
error: string | null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const ${name}: React.FC<Props> = ({ style, children }) => {
|
|
62
|
+
const navigation = useNavigation();
|
|
63
|
+
const [state, setState] = useState<State>({ loading: false, error: null });
|
|
64
|
+
|
|
65
|
+
React.useEffect(() => {
|
|
66
|
+
// TODO: Initialize component data
|
|
67
|
+
}, []);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<View style={[styles.container, style]}>
|
|
71
|
+
{state.loading ? (
|
|
72
|
+
<View style={styles.centerContent}>
|
|
73
|
+
{/* Loading indicator */}
|
|
74
|
+
</View>
|
|
75
|
+
) : state.error ? (
|
|
76
|
+
<View style={styles.centerContent}>
|
|
77
|
+
{/* Error display */}
|
|
78
|
+
</View>
|
|
79
|
+
) : (
|
|
80
|
+
children
|
|
81
|
+
)}
|
|
82
|
+
</View>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default ${name};
|
|
87
|
+
|
|
88
|
+
const styles = StyleSheet.create({
|
|
89
|
+
container: {
|
|
90
|
+
flex: 1,
|
|
91
|
+
},
|
|
92
|
+
centerContent: {
|
|
93
|
+
flex: 1,
|
|
94
|
+
alignItems: 'center',
|
|
95
|
+
justifyContent: 'center',
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getScreenTemplate = getScreenTemplate;
|
|
4
|
+
function getScreenTemplate(name, type) {
|
|
5
|
+
switch (type) {
|
|
6
|
+
case 'list':
|
|
7
|
+
return listScreenTemplate(name);
|
|
8
|
+
case 'form':
|
|
9
|
+
return formScreenTemplate(name);
|
|
10
|
+
case 'detail':
|
|
11
|
+
return detailScreenTemplate(name);
|
|
12
|
+
default:
|
|
13
|
+
return basicScreenTemplate(name);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function basicScreenTemplate(name) {
|
|
17
|
+
return `import React from 'react';
|
|
18
|
+
import { View, Text, StyleSheet } from 'react-native';
|
|
19
|
+
import { useNavigation } from '@react-navigation/native';
|
|
20
|
+
|
|
21
|
+
const ${name} = () => {
|
|
22
|
+
const navigation = useNavigation();
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<View style={styles.container}>
|
|
26
|
+
<Text style={styles.title}>${name}</Text>
|
|
27
|
+
</View>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default ${name};
|
|
32
|
+
|
|
33
|
+
const styles = StyleSheet.create({
|
|
34
|
+
container: {
|
|
35
|
+
flex: 1,
|
|
36
|
+
alignItems: 'center',
|
|
37
|
+
justifyContent: 'center',
|
|
38
|
+
paddingHorizontal: 16,
|
|
39
|
+
},
|
|
40
|
+
title: {
|
|
41
|
+
fontSize: 24,
|
|
42
|
+
fontWeight: 'bold',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
function listScreenTemplate(name) {
|
|
48
|
+
return `import React, { useState } from 'react';
|
|
49
|
+
import { View, Text, FlatList, StyleSheet, ActivityIndicator } from 'react-native';
|
|
50
|
+
import { useNavigation } from '@react-navigation/native';
|
|
51
|
+
|
|
52
|
+
interface Item {
|
|
53
|
+
id: string;
|
|
54
|
+
title: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const ${name} = () => {
|
|
58
|
+
const navigation = useNavigation();
|
|
59
|
+
const [items, setItems] = useState<Item[]>([]);
|
|
60
|
+
const [loading, setLoading] = useState(false);
|
|
61
|
+
|
|
62
|
+
const renderItem = ({ item }: { item: Item }) => (
|
|
63
|
+
<View style={styles.itemContainer}>
|
|
64
|
+
<Text style={styles.itemTitle}>{item.title}</Text>
|
|
65
|
+
</View>
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<View style={styles.container}>
|
|
70
|
+
<Text style={styles.title}>${name}</Text>
|
|
71
|
+
{loading ? (
|
|
72
|
+
<ActivityIndicator size="large" color="#007AFF" />
|
|
73
|
+
) : (
|
|
74
|
+
<FlatList
|
|
75
|
+
data={items}
|
|
76
|
+
renderItem={renderItem}
|
|
77
|
+
keyExtractor={(item) => item.id}
|
|
78
|
+
contentContainerStyle={styles.listContent}
|
|
79
|
+
/>
|
|
80
|
+
)}
|
|
81
|
+
</View>
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export default ${name};
|
|
86
|
+
|
|
87
|
+
const styles = StyleSheet.create({
|
|
88
|
+
container: {
|
|
89
|
+
flex: 1,
|
|
90
|
+
paddingHorizontal: 16,
|
|
91
|
+
paddingTop: 12,
|
|
92
|
+
},
|
|
93
|
+
title: {
|
|
94
|
+
fontSize: 24,
|
|
95
|
+
fontWeight: 'bold',
|
|
96
|
+
marginBottom: 16,
|
|
97
|
+
},
|
|
98
|
+
listContent: {
|
|
99
|
+
paddingBottom: 16,
|
|
100
|
+
},
|
|
101
|
+
itemContainer: {
|
|
102
|
+
paddingVertical: 12,
|
|
103
|
+
paddingHorizontal: 12,
|
|
104
|
+
marginBottom: 8,
|
|
105
|
+
backgroundColor: '#f5f5f5',
|
|
106
|
+
borderRadius: 8,
|
|
107
|
+
},
|
|
108
|
+
itemTitle: {
|
|
109
|
+
fontSize: 16,
|
|
110
|
+
fontWeight: '500',
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
`;
|
|
114
|
+
}
|
|
115
|
+
function formScreenTemplate(name) {
|
|
116
|
+
return `import React, { useState } from 'react';
|
|
117
|
+
import { View, Text, TextInput, StyleSheet, TouchableOpacity, ScrollView } from 'react-native';
|
|
118
|
+
import { useNavigation } from '@react-navigation/native';
|
|
119
|
+
|
|
120
|
+
interface FormData {
|
|
121
|
+
name: string;
|
|
122
|
+
email: string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const ${name} = () => {
|
|
126
|
+
const navigation = useNavigation();
|
|
127
|
+
const [formData, setFormData] = useState<FormData>({ name: '', email: '' });
|
|
128
|
+
const [loading, setLoading] = useState(false);
|
|
129
|
+
|
|
130
|
+
const handleSubmit = async () => {
|
|
131
|
+
setLoading(true);
|
|
132
|
+
try {
|
|
133
|
+
// TODO: Submit form data
|
|
134
|
+
console.log('Form data:', formData);
|
|
135
|
+
} finally {
|
|
136
|
+
setLoading(false);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<ScrollView style={styles.container}>
|
|
142
|
+
<Text style={styles.title}>${name}</Text>
|
|
143
|
+
|
|
144
|
+
<View style={styles.formGroup}>
|
|
145
|
+
<Text style={styles.label}>Name</Text>
|
|
146
|
+
<TextInput
|
|
147
|
+
style={styles.input}
|
|
148
|
+
placeholder="Enter name"
|
|
149
|
+
value={formData.name}
|
|
150
|
+
onChangeText={(text) => setFormData({ ...formData, name: text })}
|
|
151
|
+
/>
|
|
152
|
+
</View>
|
|
153
|
+
|
|
154
|
+
<View style={styles.formGroup}>
|
|
155
|
+
<Text style={styles.label}>Email</Text>
|
|
156
|
+
<TextInput
|
|
157
|
+
style={styles.input}
|
|
158
|
+
placeholder="Enter email"
|
|
159
|
+
value={formData.email}
|
|
160
|
+
onChangeText={(text) => setFormData({ ...formData, email: text })}
|
|
161
|
+
keyboardType="email-address"
|
|
162
|
+
/>
|
|
163
|
+
</View>
|
|
164
|
+
|
|
165
|
+
<TouchableOpacity
|
|
166
|
+
style={[styles.button, loading && styles.buttonDisabled]}
|
|
167
|
+
onPress={handleSubmit}
|
|
168
|
+
disabled={loading}
|
|
169
|
+
>
|
|
170
|
+
<Text style={styles.buttonText}>{loading ? 'Submitting...' : 'Submit'}</Text>
|
|
171
|
+
</TouchableOpacity>
|
|
172
|
+
</ScrollView>
|
|
173
|
+
);
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export default ${name};
|
|
177
|
+
|
|
178
|
+
const styles = StyleSheet.create({
|
|
179
|
+
container: {
|
|
180
|
+
flex: 1,
|
|
181
|
+
paddingHorizontal: 16,
|
|
182
|
+
paddingTop: 16,
|
|
183
|
+
},
|
|
184
|
+
title: {
|
|
185
|
+
fontSize: 24,
|
|
186
|
+
fontWeight: 'bold',
|
|
187
|
+
marginBottom: 24,
|
|
188
|
+
},
|
|
189
|
+
formGroup: {
|
|
190
|
+
marginBottom: 16,
|
|
191
|
+
},
|
|
192
|
+
label: {
|
|
193
|
+
fontSize: 14,
|
|
194
|
+
fontWeight: '600',
|
|
195
|
+
marginBottom: 8,
|
|
196
|
+
color: '#333',
|
|
197
|
+
},
|
|
198
|
+
input: {
|
|
199
|
+
borderWidth: 1,
|
|
200
|
+
borderColor: '#ddd',
|
|
201
|
+
borderRadius: 8,
|
|
202
|
+
paddingHorizontal: 12,
|
|
203
|
+
paddingVertical: 10,
|
|
204
|
+
fontSize: 14,
|
|
205
|
+
},
|
|
206
|
+
button: {
|
|
207
|
+
backgroundColor: '#007AFF',
|
|
208
|
+
borderRadius: 8,
|
|
209
|
+
paddingVertical: 12,
|
|
210
|
+
alignItems: 'center',
|
|
211
|
+
marginTop: 24,
|
|
212
|
+
marginBottom: 30,
|
|
213
|
+
},
|
|
214
|
+
buttonDisabled: {
|
|
215
|
+
opacity: 0.6,
|
|
216
|
+
},
|
|
217
|
+
buttonText: {
|
|
218
|
+
color: '#fff',
|
|
219
|
+
fontSize: 16,
|
|
220
|
+
fontWeight: '600',
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
`;
|
|
224
|
+
}
|
|
225
|
+
function detailScreenTemplate(name) {
|
|
226
|
+
return `import React, { useState } from 'react';
|
|
227
|
+
import { View, Text, StyleSheet, ScrollView, TouchableOpacity, ActivityIndicator } from 'react-native';
|
|
228
|
+
import { useNavigation, useRoute } from '@react-navigation/native';
|
|
229
|
+
|
|
230
|
+
interface DetailData {
|
|
231
|
+
id: string;
|
|
232
|
+
title: string;
|
|
233
|
+
description: string;
|
|
234
|
+
status: string;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const ${name} = () => {
|
|
238
|
+
const navigation = useNavigation();
|
|
239
|
+
const route = useRoute<any>();
|
|
240
|
+
const [data, setData] = useState<DetailData | null>(null);
|
|
241
|
+
const [loading, setLoading] = useState(true);
|
|
242
|
+
|
|
243
|
+
React.useEffect(() => {
|
|
244
|
+
// TODO: Fetch detail data
|
|
245
|
+
setLoading(false);
|
|
246
|
+
}, []);
|
|
247
|
+
|
|
248
|
+
if (loading) {
|
|
249
|
+
return (
|
|
250
|
+
<View style={styles.centerContainer}>
|
|
251
|
+
<ActivityIndicator size="large" color="#007AFF" />
|
|
252
|
+
</View>
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (!data) {
|
|
257
|
+
return (
|
|
258
|
+
<View style={styles.centerContainer}>
|
|
259
|
+
<Text style={styles.errorText}>No data found</Text>
|
|
260
|
+
</View>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return (
|
|
265
|
+
<ScrollView style={styles.container}>
|
|
266
|
+
<Text style={styles.title}>{data.title}</Text>
|
|
267
|
+
|
|
268
|
+
<View style={styles.section}>
|
|
269
|
+
<Text style={styles.sectionLabel}>Description</Text>
|
|
270
|
+
<Text style={styles.description}>{data.description}</Text>
|
|
271
|
+
</View>
|
|
272
|
+
|
|
273
|
+
<View style={styles.section}>
|
|
274
|
+
<Text style={styles.sectionLabel}>Status</Text>
|
|
275
|
+
<Text style={[styles.status, { color: data.status === 'active' ? '#4CAF50' : '#FF9800' }]}>
|
|
276
|
+
{data.status}
|
|
277
|
+
</Text>
|
|
278
|
+
</View>
|
|
279
|
+
|
|
280
|
+
<TouchableOpacity style={styles.editButton}>
|
|
281
|
+
<Text style={styles.editButtonText}>Edit</Text>
|
|
282
|
+
</TouchableOpacity>
|
|
283
|
+
</ScrollView>
|
|
284
|
+
);
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
export default ${name};
|
|
288
|
+
|
|
289
|
+
const styles = StyleSheet.create({
|
|
290
|
+
container: {
|
|
291
|
+
flex: 1,
|
|
292
|
+
paddingHorizontal: 16,
|
|
293
|
+
paddingTop: 16,
|
|
294
|
+
},
|
|
295
|
+
centerContainer: {
|
|
296
|
+
flex: 1,
|
|
297
|
+
alignItems: 'center',
|
|
298
|
+
justifyContent: 'center',
|
|
299
|
+
},
|
|
300
|
+
title: {
|
|
301
|
+
fontSize: 24,
|
|
302
|
+
fontWeight: 'bold',
|
|
303
|
+
marginBottom: 24,
|
|
304
|
+
},
|
|
305
|
+
section: {
|
|
306
|
+
marginBottom: 24,
|
|
307
|
+
},
|
|
308
|
+
sectionLabel: {
|
|
309
|
+
fontSize: 14,
|
|
310
|
+
fontWeight: '600',
|
|
311
|
+
marginBottom: 8,
|
|
312
|
+
color: '#666',
|
|
313
|
+
},
|
|
314
|
+
description: {
|
|
315
|
+
fontSize: 14,
|
|
316
|
+
lineHeight: 20,
|
|
317
|
+
color: '#333',
|
|
318
|
+
},
|
|
319
|
+
status: {
|
|
320
|
+
fontSize: 14,
|
|
321
|
+
fontWeight: '600',
|
|
322
|
+
},
|
|
323
|
+
errorText: {
|
|
324
|
+
fontSize: 16,
|
|
325
|
+
color: '#f44336',
|
|
326
|
+
},
|
|
327
|
+
editButton: {
|
|
328
|
+
backgroundColor: '#007AFF',
|
|
329
|
+
borderRadius: 8,
|
|
330
|
+
paddingVertical: 12,
|
|
331
|
+
alignItems: 'center',
|
|
332
|
+
marginTop: 24,
|
|
333
|
+
marginBottom: 30,
|
|
334
|
+
},
|
|
335
|
+
editButtonText: {
|
|
336
|
+
color: '#fff',
|
|
337
|
+
fontSize: 16,
|
|
338
|
+
fontWeight: '600',
|
|
339
|
+
},
|
|
340
|
+
});
|
|
341
|
+
`;
|
|
342
|
+
}
|
|
@@ -4,31 +4,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.selectOption = selectOption;
|
|
7
|
-
const
|
|
7
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Interactive list prompt using inquirer
|
|
10
10
|
* Returns a typed value instead of raw string
|
|
11
11
|
*/
|
|
12
|
-
async function selectOption(message, options) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const index = Number(answer) - 1;
|
|
24
|
-
rl.close();
|
|
25
|
-
if (index >= 0 && index < options.length) {
|
|
26
|
-
resolve(options[index]);
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
console.log('\x1b[1;31mInvalid selection. Defaulting to first option.\x1b[0m');
|
|
30
|
-
resolve(options[0]);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
});
|
|
12
|
+
async function selectOption(message, options, defaultValue) {
|
|
13
|
+
const { selected } = await inquirer_1.default.prompt([
|
|
14
|
+
{
|
|
15
|
+
type: 'list',
|
|
16
|
+
name: 'selected',
|
|
17
|
+
message: message,
|
|
18
|
+
choices: [...options],
|
|
19
|
+
default: defaultValue || options[0]
|
|
20
|
+
}
|
|
21
|
+
]);
|
|
22
|
+
return selected;
|
|
34
23
|
}
|