summaryrefslogtreecommitdiff
path: root/packages/create-astro/src/components/App.tsx
blob: fd9192bb6da71cc34fce073859de36674895cc34 (plain) (blame)
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
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';
	run: boolean;
	projectExists?: boolean;
	force?: boolean;
	projectName?: string;
	template?: string;
	templates: string[];
	ready?: boolean;
}

const getStep = ({ projectName, projectExists: exists, template, force, ready }: 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: return {
			key: 'install',
			Component: Install
		};
		default: return {
			key: 'final',
			Component: Finalize
		}
    }
}

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(context.use, state.template, state.projectName).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;