feat: minimal UI for login
This commit is contained in:
@ -62,6 +62,10 @@ func main() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
r.Options("/*", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
})
|
||||||
|
|
||||||
r.Get("/image", func(w http.ResponseWriter, r *http.Request) {
|
r.Get("/image", func(w http.ResponseWriter, r *http.Request) {
|
||||||
token := r.Header.Get("Authorization")[7:]
|
token := r.Header.Get("Authorization")[7:]
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import { SearchCardLocation } from "./components/search-card/SearchCardLocation"
|
|||||||
import { UserImage, getUserImages } from "./network";
|
import { UserImage, getUserImages } from "./network";
|
||||||
import { getCardSize } from "./utils/getCardSize";
|
import { getCardSize } from "./utils/getCardSize";
|
||||||
import { SearchCardNote } from "./components/search-card/SearchCardNote";
|
import { SearchCardNote } from "./components/search-card/SearchCardNote";
|
||||||
|
import { A } from "@solidjs/router";
|
||||||
|
|
||||||
const getCardComponent = (item: UserImage) => {
|
const getCardComponent = (item: UserImage) => {
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
@ -99,6 +100,7 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<main class="container pt-2">
|
<main class="container pt-2">
|
||||||
|
<A href="login">login</A>
|
||||||
<div class="px-4">
|
<div class="px-4">
|
||||||
<div class="inline-flex justify-between w-full rounded-xl text-base leading-none outline-none bg-white border border-neutral-200 text-neutral-900">
|
<div class="inline-flex justify-between w-full rounded-xl text-base leading-none outline-none bg-white border border-neutral-200 text-neutral-900">
|
||||||
<div class="appearance-none inline-flex justify-center items-center w-auto outline-none rounded-l-md px-2.5 text-gray-900">
|
<div class="appearance-none inline-flex justify-center items-center w-auto outline-none rounded-l-md px-2.5 text-gray-900">
|
||||||
|
48
frontend/src/Login.tsx
Normal file
48
frontend/src/Login.tsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { Button } from "@kobalte/core/button";
|
||||||
|
import { TextField } from "@kobalte/core/text-field";
|
||||||
|
import { createSignal, Show, type Component } from "solid-js";
|
||||||
|
import { postCode, postLogin } from "./network";
|
||||||
|
|
||||||
|
export const Login: Component = () => {
|
||||||
|
let form: HTMLFormElement | undefined;
|
||||||
|
|
||||||
|
const [submitted, setSubmitted] = createSignal(false);
|
||||||
|
|
||||||
|
const onSubmit: HTMLFormElement["onsubmit"] = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const formData = new FormData(form);
|
||||||
|
const email = formData.get("email");
|
||||||
|
if (email == null) {
|
||||||
|
throw new Error("bruh, no email");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!submitted()) {
|
||||||
|
await postLogin(email.toString());
|
||||||
|
setSubmitted(true);
|
||||||
|
} else {
|
||||||
|
const code = formData.get("code");
|
||||||
|
if (code == null) {
|
||||||
|
throw new Error("bruh, no code");
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await postCode(email.toString(), code.toString());
|
||||||
|
console.log(res);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form ref={form} onSubmit={onSubmit}>
|
||||||
|
<TextField name="email">
|
||||||
|
<TextField.Label>Email</TextField.Label>
|
||||||
|
<TextField.Input />
|
||||||
|
</TextField>
|
||||||
|
<Show when={submitted()}>
|
||||||
|
<TextField name="code">
|
||||||
|
<TextField.Label>Code</TextField.Label>
|
||||||
|
<TextField.Input />
|
||||||
|
</TextField>
|
||||||
|
</Show>
|
||||||
|
<Button type="submit">Submit</Button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
@ -4,11 +4,13 @@ import App from "./App";
|
|||||||
import "./index.css";
|
import "./index.css";
|
||||||
import { Route, Router } from "@solidjs/router";
|
import { Route, Router } from "@solidjs/router";
|
||||||
import { ImagePage } from "./ImagePage";
|
import { ImagePage } from "./ImagePage";
|
||||||
|
import { Login } from "./Login";
|
||||||
|
|
||||||
render(
|
render(
|
||||||
() => (
|
() => (
|
||||||
<Router>
|
<Router>
|
||||||
<Route path="/" component={App} />
|
<Route path="/" component={App} />
|
||||||
|
<Route path="/login" component={Login} />
|
||||||
<Route path="/image/:imageId" component={ImagePage} />
|
<Route path="/image/:imageId" component={ImagePage} />
|
||||||
</Router>
|
</Router>
|
||||||
),
|
),
|
||||||
|
@ -113,3 +113,33 @@ export const getUserImages = async (): Promise<UserImage[]> => {
|
|||||||
|
|
||||||
return parse(getUserImagesResponseValidator, res);
|
return parse(getUserImagesResponseValidator, res);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const postLogin = async (email: string): Promise<void> => {
|
||||||
|
const request = getBaseRequest({
|
||||||
|
path: "login",
|
||||||
|
body: JSON.stringify({ email }),
|
||||||
|
method: "POST",
|
||||||
|
});
|
||||||
|
|
||||||
|
await fetch(request);
|
||||||
|
};
|
||||||
|
|
||||||
|
const codeValidator = strictObject({
|
||||||
|
access: string(),
|
||||||
|
refresh: string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const postCode = async (
|
||||||
|
email: string,
|
||||||
|
code: string,
|
||||||
|
): Promise<InferOutput<typeof codeValidator>> => {
|
||||||
|
const request = getBaseRequest({
|
||||||
|
path: "code",
|
||||||
|
body: JSON.stringify({ email, code }),
|
||||||
|
method: "POST",
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await fetch(request).then((res) => res.json());
|
||||||
|
|
||||||
|
return parse(codeValidator, res);
|
||||||
|
};
|
||||||
|
Reference in New Issue
Block a user