mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-10-29 21:25:43 +00:00
Initial Commit
This commit is contained in:
53
site/src/pages/continue-page.tsx
Normal file
53
site/src/pages/continue-page.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Button, Paper, Text } from "@mantine/core";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { Navigate } from "react-router";
|
||||
import { useUserContext } from "../context/user-context";
|
||||
import { Layout } from "../components/layouts/layout";
|
||||
|
||||
export const ContinuePage = () => {
|
||||
const queryString = window.location.search;
|
||||
const params = new URLSearchParams(queryString);
|
||||
const redirectUri = params.get("redirect_uri");
|
||||
|
||||
const { isLoggedIn } = useUserContext();
|
||||
|
||||
if (!isLoggedIn) {
|
||||
return <Navigate to="/login" />;
|
||||
}
|
||||
|
||||
const redirect = () => {
|
||||
notifications.show({
|
||||
title: "Redirecting",
|
||||
message: "You should be redirected to the app soon",
|
||||
color: "blue",
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.replace(redirectUri!);
|
||||
}, 500);
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Paper shadow="md" p={30} mt={30} radius="md" withBorder>
|
||||
{redirectUri ? (
|
||||
<>
|
||||
<Text size="xl" fw={700}>
|
||||
Continue
|
||||
</Text>
|
||||
<Text>Click the button to continue to your app.</Text>
|
||||
<Button fullWidth mt="xl" onClick={redirect}>
|
||||
Continue
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Text size="xl" fw={700}>
|
||||
Logged in
|
||||
</Text>
|
||||
<Text>You are now signed in and can use your apps.</Text>
|
||||
</>
|
||||
)}
|
||||
</Paper>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
99
site/src/pages/login-page.tsx
Normal file
99
site/src/pages/login-page.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import { Button, Paper, PasswordInput, TextInput, Title } from "@mantine/core";
|
||||
import { useForm, zodResolver } from "@mantine/form";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
import { z } from "zod";
|
||||
import { useUserContext } from "../context/user-context";
|
||||
import { Navigate } from "react-router";
|
||||
import { Layout } from "../components/layouts/layout";
|
||||
|
||||
export const LoginPage = () => {
|
||||
const queryString = window.location.search;
|
||||
const params = new URLSearchParams(queryString);
|
||||
const redirectUri = params.get("redirect_uri");
|
||||
|
||||
const { isLoggedIn } = useUserContext();
|
||||
|
||||
if (isLoggedIn) {
|
||||
return <Navigate to="/logout" />;
|
||||
}
|
||||
|
||||
const schema = z.object({
|
||||
email: z.string().email({ message: "Invalid email" }),
|
||||
password: z.string(),
|
||||
});
|
||||
|
||||
type FormValues = z.infer<typeof schema>;
|
||||
|
||||
const form = useForm({
|
||||
mode: "uncontrolled",
|
||||
initialValues: {
|
||||
email: "",
|
||||
password: "",
|
||||
},
|
||||
validate: zodResolver(schema),
|
||||
});
|
||||
|
||||
const loginMutation = useMutation({
|
||||
mutationFn: (login: FormValues) => {
|
||||
return axios.post("/api/login", login);
|
||||
},
|
||||
onError: () => {
|
||||
notifications.show({
|
||||
title: "Failed to login",
|
||||
message: "Check your email and password",
|
||||
color: "red",
|
||||
});
|
||||
},
|
||||
onSuccess: () => {
|
||||
notifications.show({
|
||||
title: "Logged in",
|
||||
message: "Welcome back!",
|
||||
color: "green",
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.replace(`/continue?redirect_uri=${redirectUri}`);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const handleSubmit = (values: FormValues) => {
|
||||
loginMutation.mutate(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Title ta="center">Welcome back!</Title>
|
||||
<Paper shadow="md" p={30} mt={30} radius="md" withBorder>
|
||||
<form onSubmit={form.onSubmit(handleSubmit)}>
|
||||
<TextInput
|
||||
label="Email"
|
||||
placeholder="you@example.com"
|
||||
required
|
||||
disabled={loginMutation.isLoading}
|
||||
key={form.key("email")}
|
||||
{...form.getInputProps("email")}
|
||||
/>
|
||||
<PasswordInput
|
||||
label="Password"
|
||||
placeholder="password"
|
||||
required
|
||||
mt="md"
|
||||
disabled={loginMutation.isLoading}
|
||||
key={form.key("password")}
|
||||
{...form.getInputProps("password")}
|
||||
/>
|
||||
<Button
|
||||
fullWidth
|
||||
mt="xl"
|
||||
type="submit"
|
||||
loading={loginMutation.isLoading}
|
||||
>
|
||||
Sign in
|
||||
</Button>
|
||||
</form>
|
||||
</Paper>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
59
site/src/pages/logout-page.tsx
Normal file
59
site/src/pages/logout-page.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import { Button, Paper, Text } from "@mantine/core";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
import { useUserContext } from "../context/user-context";
|
||||
import { Navigate } from "react-router";
|
||||
import { Layout } from "../components/layouts/layout";
|
||||
|
||||
export const LogoutPage = () => {
|
||||
const { isLoggedIn } = useUserContext();
|
||||
|
||||
if (!isLoggedIn) {
|
||||
return <Navigate to="/login" />;
|
||||
}
|
||||
|
||||
const logoutMutation = useMutation({
|
||||
mutationFn: () => {
|
||||
return axios.post("/api/logout");
|
||||
},
|
||||
onError: () => {
|
||||
notifications.show({
|
||||
title: "Failed to logout",
|
||||
message: "Please try again",
|
||||
color: "red",
|
||||
});
|
||||
},
|
||||
onSuccess: () => {
|
||||
notifications.show({
|
||||
title: "Logged out",
|
||||
message: "Goodbye!",
|
||||
color: "green",
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Paper shadow="md" p={30} mt={30} radius="md" withBorder>
|
||||
<Text size="xl" fw={700}>
|
||||
Logout
|
||||
</Text>
|
||||
<Text>
|
||||
You are already logged in, click the button below to log out.
|
||||
</Text>
|
||||
<Button
|
||||
fullWidth
|
||||
mt="xl"
|
||||
onClick={() => logoutMutation.mutate()}
|
||||
loading={logoutMutation.isLoading}
|
||||
>
|
||||
Logout
|
||||
</Button>
|
||||
</Paper>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
18
site/src/pages/not-found-page.tsx
Normal file
18
site/src/pages/not-found-page.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Button, Paper, Text } from "@mantine/core";
|
||||
import { Layout } from "../components/layouts/layout";
|
||||
|
||||
export const NotFoundPage = () => {
|
||||
return (
|
||||
<Layout>
|
||||
<Paper shadow="md" p={30} mt={30} radius="md" withBorder>
|
||||
<Text size="xl" fw={700}>
|
||||
Not found
|
||||
</Text>
|
||||
<Text>The page you are looking for does not exist.</Text>
|
||||
<Button fullWidth mt="xl" onClick={() => window.location.replace("/")}>
|
||||
Go home
|
||||
</Button>
|
||||
</Paper>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user