mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
add setup page base
This commit is contained in:
@@ -47,6 +47,8 @@ const ProjectSettingsPage = lazy(() => import("./pages/Settings/ProjectSettings"
|
||||
const UserSettingsPage = lazy(() => import("./pages/Settings/UserSettings" /* webpackChunkName: "UserSettingsPage" */));
|
||||
// prettier-ignore
|
||||
const UserManagementPage = lazy(() => import("./pages/Settings/UserManagement" /* webpackChunkName: "UserManagementPage" */));
|
||||
// prettier-ignore
|
||||
const SetupPage = lazy(() => import("pages/Setup" /* webpackChunkName: "SetupPage" */));
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
@@ -81,6 +83,11 @@ export default function App() {
|
||||
path={routes.signOut}
|
||||
render={() => <SignOutView />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={routes.setup}
|
||||
render={() => <SetupPage />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
exact
|
||||
|
||||
81
src/assets/BrandedBackground.tsx
Normal file
81
src/assets/BrandedBackground.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import Helmet from "react-helmet";
|
||||
import { use100vh } from "react-div-100vh";
|
||||
|
||||
import { useTheme, alpha } from "@mui/material/styles";
|
||||
|
||||
import bgPattern from "assets/bg-pattern.svg";
|
||||
import bgPatternDark from "assets/bg-pattern-dark.svg";
|
||||
|
||||
export default function BrandedBackground() {
|
||||
const theme = useTheme();
|
||||
const fullScreenHeight = use100vh() ?? 0;
|
||||
|
||||
return (
|
||||
<Helmet>
|
||||
<style type="text/css">
|
||||
{`
|
||||
body {
|
||||
background-blend-mode: ${
|
||||
// prettier-ignore
|
||||
[
|
||||
"normal",
|
||||
"normal",
|
||||
"normal",
|
||||
|
||||
"overlay",
|
||||
|
||||
"normal",
|
||||
"normal",
|
||||
].join(", ")
|
||||
};
|
||||
background-size: ${
|
||||
// prettier-ignore
|
||||
[
|
||||
"100%",
|
||||
"100%",
|
||||
"100%",
|
||||
|
||||
`${480 * 10 / 14}px`,
|
||||
|
||||
"100%",
|
||||
"100%",
|
||||
].join(", ")
|
||||
};
|
||||
background-image: ${
|
||||
// prettier-ignore
|
||||
[
|
||||
`radial-gradient(circle at 85% 100%, ${theme.palette.background.paper} 20%, ${alpha(theme.palette.background.paper, 0)})`,
|
||||
`radial-gradient(80% 80% at 15% 100%, ${alpha("#FA0", 0.1)} 25%, ${alpha("#F0A", 0.1)} 50%, ${alpha("#F0A", 0)} 100%)`,
|
||||
`linear-gradient(to top, ${alpha(theme.palette.background.paper, 1)}, ${alpha(theme.palette.background.paper, 0)})`,
|
||||
|
||||
`url('${theme.palette.mode==="dark" ? bgPatternDark : bgPattern}')`,
|
||||
|
||||
`radial-gradient(60% 180% at 100% 15%, ${alpha("#0FA", 0.3)} 25%, ${alpha("#0AF", 0.2)} 50%, ${alpha("#0AF", 0)} 100%)`,
|
||||
`linear-gradient(${alpha(theme.palette.primary.main, 0.2)}, ${alpha(theme.palette.primary.main, 0.2)})`,
|
||||
].join(", ")
|
||||
};
|
||||
}
|
||||
|
||||
#root {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
|
||||
cursor: default;
|
||||
${["top", "right", "bottom", "left"]
|
||||
.map(
|
||||
(side) =>
|
||||
`padding-${side}: max(env(safe-area-inset-${side}), ${theme.spacing(
|
||||
1
|
||||
)});`
|
||||
)
|
||||
.join("\n")}
|
||||
|
||||
min-height: ${
|
||||
fullScreenHeight > 0 ? `${fullScreenHeight}px` : "100vh"
|
||||
};
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</Helmet>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
import Helmet from "react-helmet";
|
||||
import { use100vh } from "react-div-100vh";
|
||||
|
||||
import { useTheme, Paper, Typography, LinearProgress } from "@mui/material";
|
||||
import { Paper, Typography, LinearProgress } from "@mui/material";
|
||||
import { alpha } from "@mui/material/styles";
|
||||
|
||||
import bgPattern from "assets/bg-pattern.svg";
|
||||
import bgPatternDark from "assets/bg-pattern-dark.svg";
|
||||
import BrandedBackground from "assets/BrandedBackground";
|
||||
import Logo from "assets/Logo";
|
||||
|
||||
import { useAppContext } from "contexts/AppContext";
|
||||
@@ -17,74 +12,15 @@ export interface IAuthLayoutProps {
|
||||
}
|
||||
|
||||
export default function AuthLayout({ children, loading }: IAuthLayoutProps) {
|
||||
const theme = useTheme();
|
||||
const fullScreenHeight = use100vh() ?? "100vh";
|
||||
|
||||
const { projectId } = useAppContext();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<style type="text/css">
|
||||
{`
|
||||
body {
|
||||
background-blend-mode: ${
|
||||
// prettier-ignore
|
||||
[
|
||||
"normal",
|
||||
"normal",
|
||||
"normal",
|
||||
|
||||
"overlay",
|
||||
|
||||
"normal",
|
||||
"normal",
|
||||
].join(", ")
|
||||
};
|
||||
background-size: ${
|
||||
// prettier-ignore
|
||||
[
|
||||
"100%",
|
||||
"100%",
|
||||
"100%",
|
||||
|
||||
`${480 * 10 / 14}px`,
|
||||
|
||||
"100%",
|
||||
"100%",
|
||||
].join(", ")
|
||||
};
|
||||
background-image: ${
|
||||
// prettier-ignore
|
||||
[
|
||||
`radial-gradient(circle at 85% 100%, ${theme.palette.background.paper} 20%, ${alpha(theme.palette.background.paper, 0)})`,
|
||||
`radial-gradient(80% 80% at 15% 100%, ${alpha("#FA0", 0.1)} 25%, ${alpha("#F0A", 0.1)} 50%, ${alpha("#F0A", 0)} 100%)`,
|
||||
`linear-gradient(to top, ${alpha(theme.palette.background.paper, 1)}, ${alpha(theme.palette.background.paper, 0)})`,
|
||||
|
||||
`url('${theme.palette.mode==="dark" ? bgPatternDark : bgPattern}')`,
|
||||
|
||||
`radial-gradient(60% 180% at 100% 15%, ${alpha("#0FA", 0.3)} 25%, ${alpha("#0AF", 0.2)} 50%, ${alpha("#0AF", 0)} 100%)`,
|
||||
`linear-gradient(${alpha(theme.palette.primary.main, 0.2)}, ${alpha(theme.palette.primary.main, 0.2)})`,
|
||||
].join(", ")
|
||||
};
|
||||
}
|
||||
|
||||
#root {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: ${theme.spacing(1)};
|
||||
cursor: default;
|
||||
min-height: ${
|
||||
fullScreenHeight > 0 ? `${fullScreenHeight}px` : "100vh"
|
||||
};
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</Helmet>
|
||||
<BrandedBackground />
|
||||
|
||||
<Paper
|
||||
component="main"
|
||||
elevation={8}
|
||||
elevation={4}
|
||||
sx={
|
||||
{
|
||||
position: "relative",
|
||||
@@ -93,7 +29,10 @@ export default function AuthLayout({ children, loading }: IAuthLayoutProps) {
|
||||
maxWidth: 400,
|
||||
width: "100%",
|
||||
p: 4,
|
||||
boxShadow: 4,
|
||||
|
||||
backgroundColor: (theme) =>
|
||||
alpha(theme.palette.background.paper, 0.5),
|
||||
backdropFilter: "blur(20px) saturate(150%)",
|
||||
|
||||
"--spacing-contents": (theme) => theme.spacing(4),
|
||||
"& > * + *": { marginTop: "var(--spacing-contents)" },
|
||||
|
||||
@@ -35,19 +35,31 @@ export default function ScrollableDialogContent({
|
||||
|
||||
return (
|
||||
<>
|
||||
{!disableTopDivider &&
|
||||
scrollInfo.y.percentage !== null &&
|
||||
scrollInfo.y.percentage > 0 && (
|
||||
<Divider sx={{ ...dividerSx, ...topDividerSx }} />
|
||||
)}
|
||||
<Divider
|
||||
style={{
|
||||
visibility:
|
||||
!disableTopDivider &&
|
||||
scrollInfo.y.percentage !== null &&
|
||||
scrollInfo.y.percentage > 0
|
||||
? "visible"
|
||||
: "hidden",
|
||||
}}
|
||||
sx={{ ...dividerSx, ...topDividerSx }}
|
||||
/>
|
||||
|
||||
<MemoizedDialogContent {...props} setRef={setRef} />
|
||||
|
||||
{!disableBottomDivider &&
|
||||
scrollInfo.y.percentage !== null &&
|
||||
scrollInfo.y.percentage < 1 && (
|
||||
<Divider sx={{ ...dividerSx, ...bottomDividerSx }} />
|
||||
)}
|
||||
<Divider
|
||||
style={{
|
||||
visibility:
|
||||
!disableBottomDivider &&
|
||||
scrollInfo.y.percentage !== null &&
|
||||
scrollInfo.y.percentage < 1
|
||||
? "visible"
|
||||
: "hidden",
|
||||
}}
|
||||
sx={{ ...dividerSx, ...bottomDividerSx }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
115
src/pages/Setup.tsx
Normal file
115
src/pages/Setup.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import { useRouteMatch } from "react-router-dom";
|
||||
import { use100vh } from "react-div-100vh";
|
||||
|
||||
import {
|
||||
useMediaQuery,
|
||||
Paper,
|
||||
Stepper,
|
||||
Step,
|
||||
StepLabel,
|
||||
MobileStepper,
|
||||
Typography,
|
||||
DialogActions,
|
||||
Button,
|
||||
} from "@mui/material";
|
||||
import { alpha } from "@mui/material/styles";
|
||||
|
||||
import BrandedBackground from "assets/BrandedBackground";
|
||||
import ScrollableDialogContent from "components/Modal/ScrollableDialogContent";
|
||||
|
||||
import { useAppContext } from "contexts/AppContext";
|
||||
|
||||
export default function SetupPage() {
|
||||
const { params } = useRouteMatch<{ step: string }>();
|
||||
const fullScreenHeight = use100vh() ?? 0;
|
||||
const isMobile = useMediaQuery((theme: any) => theme.breakpoints.down("sm"));
|
||||
|
||||
return (
|
||||
<>
|
||||
<BrandedBackground />
|
||||
<Paper
|
||||
component="main"
|
||||
elevation={4}
|
||||
sx={{
|
||||
backgroundColor: (theme) =>
|
||||
alpha(theme.palette.background.paper, 0.5),
|
||||
backdropFilter: "blur(20px) saturate(150%)",
|
||||
|
||||
maxWidth: (theme) => theme.breakpoints.values.md,
|
||||
width: "100%",
|
||||
maxHeight: (theme) =>
|
||||
`calc(${
|
||||
fullScreenHeight > 0 ? `${fullScreenHeight}px` : "100vh"
|
||||
} - ${theme.spacing(
|
||||
2
|
||||
)} - env(safe-area-inset-top) - env(safe-area-inset-bottom))`,
|
||||
height: (theme) => theme.breakpoints.values.md * 0.75,
|
||||
|
||||
p: 0,
|
||||
"& > *": { px: { xs: 2, sm: 4 } },
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
{isMobile ? (
|
||||
<MobileStepper
|
||||
variant="dots"
|
||||
steps={4}
|
||||
backButton={null}
|
||||
nextButton={null}
|
||||
position="static"
|
||||
sx={{
|
||||
background: "none",
|
||||
m: 1,
|
||||
mt: 1.25,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Stepper
|
||||
sx={{
|
||||
mt: 2.5,
|
||||
mb: 3,
|
||||
"& .MuiStep-root:first-child": { pl: 0 },
|
||||
"& .MuiStep-root:last-child": { pr: 0 },
|
||||
userSelect: "none",
|
||||
}}
|
||||
>
|
||||
<Step>
|
||||
<StepLabel>Rowy Run</StepLabel>
|
||||
</Step>
|
||||
<Step>
|
||||
<StepLabel>Service Account</StepLabel>
|
||||
</Step>
|
||||
<Step>
|
||||
<StepLabel>Sign In</StepLabel>
|
||||
</Step>
|
||||
<Step>
|
||||
<StepLabel>Firestore Rules</StepLabel>
|
||||
</Step>
|
||||
</Stepper>
|
||||
)}
|
||||
|
||||
<Typography
|
||||
variant="h4"
|
||||
component="h1"
|
||||
sx={{ mb: 1, typography: { xs: "h5", md: "h4" } }}
|
||||
>
|
||||
Set Up Rowy Run
|
||||
</Typography>
|
||||
|
||||
<ScrollableDialogContent>
|
||||
<Typography variant="body1">
|
||||
Rowy Run is a Cloud Run instance.
|
||||
</Typography>
|
||||
<div style={{ height: "100vh" }}>content</div>
|
||||
</ScrollableDialogContent>
|
||||
|
||||
<DialogActions>
|
||||
<Button variant="contained" color="primary">
|
||||
Get Started
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Paper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -805,6 +805,29 @@ export const components = (theme: Theme): ThemeOptions => {
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
MuiStepIcon: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: theme.palette.divider,
|
||||
},
|
||||
text: {
|
||||
fontWeight: theme.typography.fontWeightBold,
|
||||
fill: theme.palette.text.secondary,
|
||||
|
||||
".Mui-active &": {
|
||||
fill: theme.palette.primary.contrastText,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiStepConnector: {
|
||||
styleOverrides: {
|
||||
line: {
|
||||
borderColor: theme.palette.divider,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user