1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
import React, { FC, useEffect } from 'react';
import { prepareTemplate, isEmpty, emptyDir } from '../utils';
import Header from './Header';
import Install from './Install';
import ProjectName from './ProjectName';
import Template from './Template';
import Confirm from './Confirm';
import Finalize from './Finalize';
interface Context {
use: 'npm' | 'yarn';
skipInstall?: boolean;
projectExists?: boolean;
force?: boolean;
projectName?: string;
template?: string;
templates: string[];
ready?: boolean;
}
const getStep = ({ projectName, projectExists: exists, template, force, ready, skipInstall }: Context) => {
switch (true) {
case !projectName:
return {
key: 'projectName',
Component: ProjectName,
};
case projectName && exists === true && typeof force === 'undefined':
return {
key: 'force',
Component: Confirm,
};
case (exists === false || force) && !template:
return {
key: 'template',
Component: Template,
};
case !ready && !skipInstall:
return {
key: 'install',
Component: Install,
};
case ready:
return {
key: 'final',
Component: Finalize,
};
default:
return {
key: 'empty',
Component: () => <></>,
};
}
};
const App: FC<{ context: Context }> = ({ context }) => {
const [state, setState] = React.useState(context);
const step = React.useRef(getStep(context));
const onSubmit = (value: string | boolean) => {
const { key } = step.current;
const newState = { ...state, [key]: value };
step.current = getStep(newState);
setState(newState);
};
useEffect(() => {
let isSubscribed = true;
if (state.projectName && typeof state.projectExists === 'undefined') {
const newState = { ...state, projectExists: !isEmpty(state.projectName) };
step.current = getStep(newState);
if (isSubscribed) {
setState(newState);
}
}
if (state.projectName && (state.projectExists === false || state.force) && state.template) {
if (state.force) emptyDir(state.projectName);
prepareTemplate({
use: context.use,
templateName: state.template,
projectName: state.projectName,
skipInstall: state.skipInstall,
}).then(() => {
if (isSubscribed) {
setState((v) => {
const newState = { ...v, ready: true };
step.current = getStep(newState);
return newState;
});
}
});
}
return () => {
isSubscribed = false;
};
}, [state]);
const { Component } = step.current;
return (
<>
<Header context={state} />
<Component context={state} onSubmit={onSubmit} />
</>
);
};
export default App;
|