summaryrefslogtreecommitdiff
path: root/packages/create-astro/src/components/App.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/create-astro/src/components/App.tsx')
-rw-r--r--packages/create-astro/src/components/App.tsx93
1 files changed, 93 insertions, 0 deletions
diff --git a/packages/create-astro/src/components/App.tsx b/packages/create-astro/src/components/App.tsx
new file mode 100644
index 000000000..fd9192bb6
--- /dev/null
+++ b/packages/create-astro/src/components/App.tsx
@@ -0,0 +1,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;