Compare commits

...
Author SHA1 Message Date
bflatastic 04dcac98e3 login error messages now show properly 2025-06-13 17:32:47 +07:00
2 changed files with 109 additions and 59 deletions
+91 -54
View File
@@ -1,7 +1,34 @@
import { ApiManager, ApiResponse } from "./ApiManager.js";
import { UserInfo } from "./models/Users.js";
import { FetchProxy as fetch } from "@storyteller/tauri-utils";
export class UsersApi extends ApiManager {
private async authFetch<B, T>(
endpoint: string,
{
method,
body,
}: {
method: string;
body?: B;
}
): Promise<T> {
const bodyInString = JSON.stringify(body);
const response = await fetch(endpoint, {
method,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
credentials: "include",
body: bodyInString,
});
const responseData = await response.json();
return responseData as T;
}
public GetSession(): Promise<
ApiResponse<{
loggedIn: boolean;
@@ -25,7 +52,7 @@ export class UsersApi extends ApiManager {
.catch((err) => {
return {
success: false,
errorMessage: err.mesasge,
errorMessage: err.message,
};
});
}
@@ -51,7 +78,7 @@ export class UsersApi extends ApiManager {
.catch((err) => {
return {
success: false,
error_message: err.message,
errorMessage: err.message,
};
});
}
@@ -69,29 +96,34 @@ export class UsersApi extends ApiManager {
username_or_email: usernameOrEmail,
password: password,
};
return await this.post<
{ username_or_email: string; password: string },
{
success: boolean;
signed_session?: string;
error_message?: string;
error_type?: string;
}
>({
endpoint: endpoint,
body: body,
})
.then((response) => ({
success: response.success,
data: { signedSession: response.signed_session },
errorMessage: response.error_message,
}))
.catch((err) => {
return {
success: false,
error_message: err.message,
};
try {
const response = await this.authFetch<
{ username_or_email: string; password: string },
{
success: boolean;
signed_session?: string;
error_message?: string;
error_type?: string;
}
>(endpoint, {
method: "POST",
body: body,
});
return {
success: response.success,
data: response.success
? { signedSession: response.signed_session }
: undefined,
errorMessage: response.error_message,
};
} catch (err: any) {
return {
success: false,
errorMessage: err.message,
};
}
}
public Logout(): Promise<ApiResponse<null>> {
@@ -128,36 +160,41 @@ export class UsersApi extends ApiManager {
password_confirmation: passwordConfirmation,
username,
};
return await this.post<
{
username: string;
email_address: string;
password: string;
password_confirmation: string;
},
{
success: boolean;
signed_session?: string;
error_fields?: Record<string, string>;
error_message?: string;
error_type?: string;
}
>({
endpoint: endpoint,
body: body,
})
.then((response) => {
return {
success: response.success,
data: { signedSession: response.signed_session },
errorMessage: Object.values(response.error_fields ?? {}).join(","),
};
})
.catch((err) => {
return {
success: false,
error_message: err.message,
};
try {
const response = await this.authFetch<
{
username: string;
email_address: string;
password: string;
password_confirmation: string;
},
{
success: boolean;
signed_session?: string;
error_fields?: Record<string, string>;
error_message?: string;
error_type?: string;
}
>(endpoint, {
method: "POST",
body: body,
});
return {
success: response.success,
data: response.success
? { signedSession: response.signed_session }
: undefined,
errorMessage:
response.error_message ||
Object.values(response.error_fields ?? {}).join(", "),
};
} catch (err: any) {
return {
success: false,
errorMessage: err.message,
};
}
}
}
@@ -1,7 +1,13 @@
import React, { useState, useEffect } from "react";
import { Input } from "@storyteller/ui-input";
import { Button } from "@storyteller/ui-button";
import { faUser, faKey, faEnvelope } from "@fortawesome/pro-solid-svg-icons";
import {
faUser,
faKey,
faEnvelope,
faExclamationTriangle,
} from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
interface ArtCraftSignUpProps {
onSubmit: (
@@ -26,7 +32,13 @@ export const ArtCraftSignUp = ({
const [localError, setLocalError] = useState<string | undefined>(undefined);
useEffect(() => {
setLocalError(errorMessage);
if (errorMessage) {
setLocalError(
errorMessage.charAt(0).toUpperCase() + errorMessage.slice(1)
);
} else {
setLocalError(undefined);
}
}, [errorMessage]);
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
@@ -120,8 +132,8 @@ export const ArtCraftSignUp = ({
/>
)}
<button type="submit" className="hidden" />
<div className="relative mt-3">
<div className="flex gap-2 items-center justify-center p-2 bg-white/5 rounded-lg">
<div className="relative mt-3 flex flex-col items-center justify-center">
<div className="flex gap-2 items-center justify-center p-2 px-3 bg-white/5 rounded-lg">
<p className="text-sm opacity-80">
{isSignUp ? "Already have an account?" : "Don't have an account?"}{" "}
</p>
@@ -137,7 +149,8 @@ export const ArtCraftSignUp = ({
</Button>
</div>
{localError && (
<div className="absolute -bottom-10 left-0 right-0 text-red text-sm text-center mb-2 font-semibold">
<div className="absolute w-fit -bottom-12 left-1/2 -translate-x-1/2 text-red bg-red/10 border border-red/20 rounded-lg py-1 px-2 justify-center text-sm text-center mb-2 font-semibold flex items-center gap-2">
<FontAwesomeIcon icon={faExclamationTriangle} />
{localError}
</div>
)}