From 4239d93ea6ea4e39c5cccb5146ca275a388446d4 Mon Sep 17 00:00:00 2001 From: Alejandra <90076947+alejsdev@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:53:33 -0500 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20and=20tweaks,?= =?UTF-8?q?=20rename=20`UserCreateOpen`=20to=20`UserRegister`=20and=20othe?= =?UTF-8?q?rs=20(#1143)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/routes/users.py | 8 +- backend/app/models.py | 2 +- backend/app/tests/api/routes/test_users.py | 12 +-- frontend/src/client/index.ts | 4 +- .../{UserCreateOpen.ts => UserRegister.ts} | 2 +- .../schemas/$Body_login_login_access_token.ts | 60 +++++++------- .../client/schemas/$HTTPValidationError.ts | 10 +-- frontend/src/client/schemas/$ItemCreate.ts | 20 ++--- frontend/src/client/schemas/$ItemOut.ts | 32 ++++---- frontend/src/client/schemas/$ItemUpdate.ts | 28 +++---- frontend/src/client/schemas/$ItemsOut.ts | 18 ++--- frontend/src/client/schemas/$Message.ts | 6 +- frontend/src/client/schemas/$NewPassword.ts | 12 +-- frontend/src/client/schemas/$Token.ts | 10 +-- .../src/client/schemas/$UpdatePassword.ts | 12 +-- frontend/src/client/schemas/$UserCreate.ts | 34 ++++---- .../src/client/schemas/$UserCreateOpen.ts | 24 ------ frontend/src/client/schemas/$UserOut.ts | 34 ++++---- frontend/src/client/schemas/$UserRegister.ts | 24 ++++++ frontend/src/client/schemas/$UserUpdate.ts | 50 ++++++------ frontend/src/client/schemas/$UserUpdateMe.ts | 28 +++---- frontend/src/client/schemas/$UsersOut.ts | 18 ++--- .../src/client/schemas/$ValidationError.ts | 34 ++++---- frontend/src/client/services/ItemsService.ts | 48 +++++------ frontend/src/client/services/LoginService.ts | 47 ++++++++--- frontend/src/client/services/UsersService.ts | 80 +++++++++---------- frontend/src/client/services/UtilsService.ts | 30 +------ frontend/src/components/Admin/AddUser.tsx | 33 ++++---- frontend/src/components/Admin/EditUser.tsx | 32 ++++---- frontend/src/components/Common/Navbar.tsx | 2 +- frontend/src/components/Common/Sidebar.tsx | 4 +- .../src/components/Common/SidebarItems.tsx | 12 +-- frontend/src/components/Common/UserMenu.tsx | 2 +- frontend/src/components/Items/AddItem.tsx | 33 ++++---- frontend/src/components/Items/EditItem.tsx | 34 ++++---- .../UserSettings/ChangePassword.tsx | 44 ++++------ .../UserSettings/DeleteConfirmation.tsx | 41 +++++----- .../UserSettings/UserInformation.tsx | 35 ++++---- frontend/src/hooks/useAuth.ts | 24 +++++- frontend/src/routes/_layout/admin.tsx | 2 +- frontend/src/routes/_layout/items.tsx | 2 +- frontend/src/routes/login.tsx | 14 +--- frontend/src/routes/reset-password.tsx | 16 +--- frontend/src/theme.tsx | 7 +- frontend/src/utils.ts | 31 +++++++ 45 files changed, 537 insertions(+), 518 deletions(-) rename frontend/src/client/models/{UserCreateOpen.ts => UserRegister.ts} (87%) delete mode 100644 frontend/src/client/schemas/$UserCreateOpen.ts create mode 100644 frontend/src/client/schemas/$UserRegister.ts diff --git a/backend/app/api/routes/users.py b/backend/app/api/routes/users.py index c171e24..598cebd 100644 --- a/backend/app/api/routes/users.py +++ b/backend/app/api/routes/users.py @@ -17,8 +17,8 @@ from app.models import ( UpdatePassword, User, UserCreate, - UserCreateOpen, UserOut, + UserRegister, UsersOut, UserUpdate, UserUpdateMe, @@ -122,8 +122,8 @@ def read_user_me(session: SessionDep, current_user: CurrentUser) -> Any: return current_user -@router.post("/open", response_model=UserOut) -def create_user_open(session: SessionDep, user_in: UserCreateOpen) -> Any: +@router.post("/signup", response_model=UserOut) +def register_user(session: SessionDep, user_in: UserRegister) -> Any: """ Create new user without the need to be logged in. """ @@ -138,7 +138,7 @@ def create_user_open(session: SessionDep, user_in: UserCreateOpen) -> Any: status_code=400, detail="The user with this email already exists in the system", ) - user_create = UserCreate.from_orm(user_in) + user_create = UserCreate.model_validate(user_in) user = crud.create_user(session=session, user_create=user_create) return user diff --git a/backend/app/models.py b/backend/app/models.py index 6b50650..16221a6 100644 --- a/backend/app/models.py +++ b/backend/app/models.py @@ -16,7 +16,7 @@ class UserCreate(UserBase): # TODO replace email str with EmailStr when sqlmodel supports it -class UserCreateOpen(SQLModel): +class UserRegister(SQLModel): email: str password: str full_name: str | None = None diff --git a/backend/app/tests/api/routes/test_users.py b/backend/app/tests/api/routes/test_users.py index 320ff5f..f37920b 100644 --- a/backend/app/tests/api/routes/test_users.py +++ b/backend/app/tests/api/routes/test_users.py @@ -263,14 +263,14 @@ def test_update_password_me_same_password_error( ) -def test_create_user_open(client: TestClient) -> None: +def test_register_user(client: TestClient) -> None: with patch("app.core.config.settings.USERS_OPEN_REGISTRATION", True): username = random_email() password = random_lower_string() full_name = random_lower_string() data = {"email": username, "password": password, "full_name": full_name} r = client.post( - f"{settings.API_V1_STR}/users/open", + f"{settings.API_V1_STR}/users/signup", json=data, ) assert r.status_code == 200 @@ -279,14 +279,14 @@ def test_create_user_open(client: TestClient) -> None: assert created_user["full_name"] == full_name -def test_create_user_open_forbidden_error(client: TestClient) -> None: +def test_register_user_forbidden_error(client: TestClient) -> None: with patch("app.core.config.settings.USERS_OPEN_REGISTRATION", False): username = random_email() password = random_lower_string() full_name = random_lower_string() data = {"email": username, "password": password, "full_name": full_name} r = client.post( - f"{settings.API_V1_STR}/users/open", + f"{settings.API_V1_STR}/users/signup", json=data, ) assert r.status_code == 403 @@ -295,7 +295,7 @@ def test_create_user_open_forbidden_error(client: TestClient) -> None: ) -def test_create_user_open_already_exists_error(client: TestClient) -> None: +def test_register_user_already_exists_error(client: TestClient) -> None: with patch("app.core.config.settings.USERS_OPEN_REGISTRATION", True): password = random_lower_string() full_name = random_lower_string() @@ -305,7 +305,7 @@ def test_create_user_open_already_exists_error(client: TestClient) -> None: "full_name": full_name, } r = client.post( - f"{settings.API_V1_STR}/users/open", + f"{settings.API_V1_STR}/users/signup", json=data, ) assert r.status_code == 400 diff --git a/frontend/src/client/index.ts b/frontend/src/client/index.ts index fb94ef6..16d2b22 100644 --- a/frontend/src/client/index.ts +++ b/frontend/src/client/index.ts @@ -18,8 +18,8 @@ export type { NewPassword } from './models/NewPassword'; export type { Token } from './models/Token'; export type { UpdatePassword } from './models/UpdatePassword'; export type { UserCreate } from './models/UserCreate'; -export type { UserCreateOpen } from './models/UserCreateOpen'; export type { UserOut } from './models/UserOut'; +export type { UserRegister } from './models/UserRegister'; export type { UsersOut } from './models/UsersOut'; export type { UserUpdate } from './models/UserUpdate'; export type { UserUpdateMe } from './models/UserUpdateMe'; @@ -36,8 +36,8 @@ export { $NewPassword } from './schemas/$NewPassword'; export { $Token } from './schemas/$Token'; export { $UpdatePassword } from './schemas/$UpdatePassword'; export { $UserCreate } from './schemas/$UserCreate'; -export { $UserCreateOpen } from './schemas/$UserCreateOpen'; export { $UserOut } from './schemas/$UserOut'; +export { $UserRegister } from './schemas/$UserRegister'; export { $UsersOut } from './schemas/$UsersOut'; export { $UserUpdate } from './schemas/$UserUpdate'; export { $UserUpdateMe } from './schemas/$UserUpdateMe'; diff --git a/frontend/src/client/models/UserCreateOpen.ts b/frontend/src/client/models/UserRegister.ts similarity index 87% rename from frontend/src/client/models/UserCreateOpen.ts rename to frontend/src/client/models/UserRegister.ts index f859e9b..f7eefa4 100644 --- a/frontend/src/client/models/UserCreateOpen.ts +++ b/frontend/src/client/models/UserRegister.ts @@ -3,7 +3,7 @@ /* tslint:disable */ /* eslint-disable */ -export type UserCreateOpen = { +export type UserRegister = { email: string; password: string; full_name?: (string | null); diff --git a/frontend/src/client/schemas/$Body_login_login_access_token.ts b/frontend/src/client/schemas/$Body_login_login_access_token.ts index 5d701cc..f545b71 100644 --- a/frontend/src/client/schemas/$Body_login_login_access_token.ts +++ b/frontend/src/client/schemas/$Body_login_login_access_token.ts @@ -5,40 +5,40 @@ export const $Body_login_login_access_token = { properties: { grant_type: { - type: 'any-of', - contains: [{ - type: 'string', - pattern: 'password', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + pattern: 'password', + }, { + type: 'null', + }], + }, username: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, password: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, scope: { - type: 'string', -}, + type: 'string', + }, client_id: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, client_secret: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, }, } as const; diff --git a/frontend/src/client/schemas/$HTTPValidationError.ts b/frontend/src/client/schemas/$HTTPValidationError.ts index 4206c7c..f8eb5c8 100644 --- a/frontend/src/client/schemas/$HTTPValidationError.ts +++ b/frontend/src/client/schemas/$HTTPValidationError.ts @@ -5,10 +5,10 @@ export const $HTTPValidationError = { properties: { detail: { - type: 'array', - contains: { - type: 'ValidationError', - }, -}, + type: 'array', + contains: { + type: 'ValidationError', + }, + }, }, } as const; diff --git a/frontend/src/client/schemas/$ItemCreate.ts b/frontend/src/client/schemas/$ItemCreate.ts index 70037ee..de80a67 100644 --- a/frontend/src/client/schemas/$ItemCreate.ts +++ b/frontend/src/client/schemas/$ItemCreate.ts @@ -5,16 +5,16 @@ export const $ItemCreate = { properties: { title: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, description: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, }, } as const; diff --git a/frontend/src/client/schemas/$ItemOut.ts b/frontend/src/client/schemas/$ItemOut.ts index 015a518..7a20bca 100644 --- a/frontend/src/client/schemas/$ItemOut.ts +++ b/frontend/src/client/schemas/$ItemOut.ts @@ -5,24 +5,24 @@ export const $ItemOut = { properties: { title: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, description: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, id: { - type: 'number', - isRequired: true, -}, + type: 'number', + isRequired: true, + }, owner_id: { - type: 'number', - isRequired: true, -}, + type: 'number', + isRequired: true, + }, }, } as const; diff --git a/frontend/src/client/schemas/$ItemUpdate.ts b/frontend/src/client/schemas/$ItemUpdate.ts index bf76d61..a7b52c5 100644 --- a/frontend/src/client/schemas/$ItemUpdate.ts +++ b/frontend/src/client/schemas/$ItemUpdate.ts @@ -5,20 +5,20 @@ export const $ItemUpdate = { properties: { title: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, description: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, }, } as const; diff --git a/frontend/src/client/schemas/$ItemsOut.ts b/frontend/src/client/schemas/$ItemsOut.ts index 782b68d..cb05328 100644 --- a/frontend/src/client/schemas/$ItemsOut.ts +++ b/frontend/src/client/schemas/$ItemsOut.ts @@ -5,15 +5,15 @@ export const $ItemsOut = { properties: { data: { - type: 'array', - contains: { - type: 'ItemOut', - }, - isRequired: true, -}, + type: 'array', + contains: { + type: 'ItemOut', + }, + isRequired: true, + }, count: { - type: 'number', - isRequired: true, -}, + type: 'number', + isRequired: true, + }, }, } as const; diff --git a/frontend/src/client/schemas/$Message.ts b/frontend/src/client/schemas/$Message.ts index d2abdc1..5d51452 100644 --- a/frontend/src/client/schemas/$Message.ts +++ b/frontend/src/client/schemas/$Message.ts @@ -5,8 +5,8 @@ export const $Message = { properties: { message: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, }, } as const; diff --git a/frontend/src/client/schemas/$NewPassword.ts b/frontend/src/client/schemas/$NewPassword.ts index f6b19e2..4959938 100644 --- a/frontend/src/client/schemas/$NewPassword.ts +++ b/frontend/src/client/schemas/$NewPassword.ts @@ -5,12 +5,12 @@ export const $NewPassword = { properties: { token: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, new_password: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, }, } as const; diff --git a/frontend/src/client/schemas/$Token.ts b/frontend/src/client/schemas/$Token.ts index 88946bc..d05d203 100644 --- a/frontend/src/client/schemas/$Token.ts +++ b/frontend/src/client/schemas/$Token.ts @@ -5,11 +5,11 @@ export const $Token = { properties: { access_token: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, token_type: { - type: 'string', -}, + type: 'string', + }, }, } as const; diff --git a/frontend/src/client/schemas/$UpdatePassword.ts b/frontend/src/client/schemas/$UpdatePassword.ts index 1875881..35828f7 100644 --- a/frontend/src/client/schemas/$UpdatePassword.ts +++ b/frontend/src/client/schemas/$UpdatePassword.ts @@ -5,12 +5,12 @@ export const $UpdatePassword = { properties: { current_password: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, new_password: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, }, } as const; diff --git a/frontend/src/client/schemas/$UserCreate.ts b/frontend/src/client/schemas/$UserCreate.ts index 84503be..8251ec9 100644 --- a/frontend/src/client/schemas/$UserCreate.ts +++ b/frontend/src/client/schemas/$UserCreate.ts @@ -5,26 +5,26 @@ export const $UserCreate = { properties: { email: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, is_active: { - type: 'boolean', -}, + type: 'boolean', + }, is_superuser: { - type: 'boolean', -}, + type: 'boolean', + }, full_name: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, password: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, }, } as const; diff --git a/frontend/src/client/schemas/$UserCreateOpen.ts b/frontend/src/client/schemas/$UserCreateOpen.ts deleted file mode 100644 index ae2fff5..0000000 --- a/frontend/src/client/schemas/$UserCreateOpen.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export const $UserCreateOpen = { - properties: { - email: { - type: 'string', - isRequired: true, -}, - password: { - type: 'string', - isRequired: true, -}, - full_name: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, - }, -} as const; diff --git a/frontend/src/client/schemas/$UserOut.ts b/frontend/src/client/schemas/$UserOut.ts index 8261402..a4f0053 100644 --- a/frontend/src/client/schemas/$UserOut.ts +++ b/frontend/src/client/schemas/$UserOut.ts @@ -5,26 +5,26 @@ export const $UserOut = { properties: { email: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, is_active: { - type: 'boolean', -}, + type: 'boolean', + }, is_superuser: { - type: 'boolean', -}, + type: 'boolean', + }, full_name: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, id: { - type: 'number', - isRequired: true, -}, + type: 'number', + isRequired: true, + }, }, } as const; diff --git a/frontend/src/client/schemas/$UserRegister.ts b/frontend/src/client/schemas/$UserRegister.ts new file mode 100644 index 0000000..4b80b7e --- /dev/null +++ b/frontend/src/client/schemas/$UserRegister.ts @@ -0,0 +1,24 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export const $UserRegister = { + properties: { + email: { + type: 'string', + isRequired: true, + }, + password: { + type: 'string', + isRequired: true, + }, + full_name: { + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, + }, +} as const; diff --git a/frontend/src/client/schemas/$UserUpdate.ts b/frontend/src/client/schemas/$UserUpdate.ts index 396e617..a87f79e 100644 --- a/frontend/src/client/schemas/$UserUpdate.ts +++ b/frontend/src/client/schemas/$UserUpdate.ts @@ -5,34 +5,34 @@ export const $UserUpdate = { properties: { email: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, is_active: { - type: 'boolean', -}, + type: 'boolean', + }, is_superuser: { - type: 'boolean', -}, + type: 'boolean', + }, full_name: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, password: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, }, } as const; diff --git a/frontend/src/client/schemas/$UserUpdateMe.ts b/frontend/src/client/schemas/$UserUpdateMe.ts index ed9c011..ad5ef55 100644 --- a/frontend/src/client/schemas/$UserUpdateMe.ts +++ b/frontend/src/client/schemas/$UserUpdateMe.ts @@ -5,20 +5,20 @@ export const $UserUpdateMe = { properties: { full_name: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, email: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'null', -}], -}, + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'null', + }], + }, }, } as const; diff --git a/frontend/src/client/schemas/$UsersOut.ts b/frontend/src/client/schemas/$UsersOut.ts index 9c22868..4aa6617 100644 --- a/frontend/src/client/schemas/$UsersOut.ts +++ b/frontend/src/client/schemas/$UsersOut.ts @@ -5,15 +5,15 @@ export const $UsersOut = { properties: { data: { - type: 'array', - contains: { - type: 'UserOut', - }, - isRequired: true, -}, + type: 'array', + contains: { + type: 'UserOut', + }, + isRequired: true, + }, count: { - type: 'number', - isRequired: true, -}, + type: 'number', + isRequired: true, + }, }, } as const; diff --git a/frontend/src/client/schemas/$ValidationError.ts b/frontend/src/client/schemas/$ValidationError.ts index b040db7..3a48f2a 100644 --- a/frontend/src/client/schemas/$ValidationError.ts +++ b/frontend/src/client/schemas/$ValidationError.ts @@ -5,24 +5,24 @@ export const $ValidationError = { properties: { loc: { - type: 'array', - contains: { - type: 'any-of', - contains: [{ - type: 'string', -}, { - type: 'number', -}], -}, - isRequired: true, -}, + type: 'array', + contains: { + type: 'any-of', + contains: [{ + type: 'string', + }, { + type: 'number', + }], + }, + isRequired: true, + }, msg: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, type: { - type: 'string', - isRequired: true, -}, + type: 'string', + isRequired: true, + }, }, } as const; diff --git a/frontend/src/client/services/ItemsService.ts b/frontend/src/client/services/ItemsService.ts index b68a28a..331581e 100644 --- a/frontend/src/client/services/ItemsService.ts +++ b/frontend/src/client/services/ItemsService.ts @@ -21,12 +21,12 @@ export class ItemsService { * @throws ApiError */ public static readItems({ -skip, -limit = 100, -}: { -skip?: number, -limit?: number, -}): CancelablePromise { + skip, + limit = 100, + }: { + skip?: number, + limit?: number, + }): CancelablePromise { return __request(OpenAPI, { method: 'GET', url: '/api/v1/items/', @@ -47,10 +47,10 @@ limit?: number, * @throws ApiError */ public static createItem({ -requestBody, -}: { -requestBody: ItemCreate, -}): CancelablePromise { + requestBody, + }: { + requestBody: ItemCreate, + }): CancelablePromise { return __request(OpenAPI, { method: 'POST', url: '/api/v1/items/', @@ -69,10 +69,10 @@ requestBody: ItemCreate, * @throws ApiError */ public static readItem({ -id, -}: { -id: number, -}): CancelablePromise { + id, + }: { + id: number, + }): CancelablePromise { return __request(OpenAPI, { method: 'GET', url: '/api/v1/items/{id}', @@ -92,12 +92,12 @@ id: number, * @throws ApiError */ public static updateItem({ -id, -requestBody, -}: { -id: number, -requestBody: ItemUpdate, -}): CancelablePromise { + id, + requestBody, + }: { + id: number, + requestBody: ItemUpdate, + }): CancelablePromise { return __request(OpenAPI, { method: 'PUT', url: '/api/v1/items/{id}', @@ -119,10 +119,10 @@ requestBody: ItemUpdate, * @throws ApiError */ public static deleteItem({ -id, -}: { -id: number, -}): CancelablePromise { + id, + }: { + id: number, + }): CancelablePromise { return __request(OpenAPI, { method: 'DELETE', url: '/api/v1/items/{id}', diff --git a/frontend/src/client/services/LoginService.ts b/frontend/src/client/services/LoginService.ts index e40899d..e7679ca 100644 --- a/frontend/src/client/services/LoginService.ts +++ b/frontend/src/client/services/LoginService.ts @@ -21,10 +21,10 @@ export class LoginService { * @throws ApiError */ public static loginAccessToken({ -formData, -}: { -formData: Body_login_login_access_token, -}): CancelablePromise { + formData, + }: { + formData: Body_login_login_access_token, + }): CancelablePromise { return __request(OpenAPI, { method: 'POST', url: '/api/v1/login/access-token', @@ -56,10 +56,10 @@ formData: Body_login_login_access_token, * @throws ApiError */ public static recoverPassword({ -email, -}: { -email: string, -}): CancelablePromise { + email, + }: { + email: string, + }): CancelablePromise { return __request(OpenAPI, { method: 'POST', url: '/api/v1/password-recovery/{email}', @@ -79,10 +79,10 @@ email: string, * @throws ApiError */ public static resetPassword({ -requestBody, -}: { -requestBody: NewPassword, -}): CancelablePromise { + requestBody, + }: { + requestBody: NewPassword, + }): CancelablePromise { return __request(OpenAPI, { method: 'POST', url: '/api/v1/reset-password/', @@ -94,4 +94,27 @@ requestBody: NewPassword, }); } + /** + * Recover Password Html Content + * HTML Content for Password Recovery + * @returns string Successful Response + * @throws ApiError + */ + public static recoverPasswordHtmlContent({ + email, + }: { + email: string, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v1/password-recovery-html-content/{email}', + path: { + 'email': email, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + } diff --git a/frontend/src/client/services/UsersService.ts b/frontend/src/client/services/UsersService.ts index 055debe..ade311d 100644 --- a/frontend/src/client/services/UsersService.ts +++ b/frontend/src/client/services/UsersService.ts @@ -5,8 +5,8 @@ import type { Message } from '../models/Message'; import type { UpdatePassword } from '../models/UpdatePassword'; import type { UserCreate } from '../models/UserCreate'; -import type { UserCreateOpen } from '../models/UserCreateOpen'; import type { UserOut } from '../models/UserOut'; +import type { UserRegister } from '../models/UserRegister'; import type { UsersOut } from '../models/UsersOut'; import type { UserUpdate } from '../models/UserUpdate'; import type { UserUpdateMe } from '../models/UserUpdateMe'; @@ -24,12 +24,12 @@ export class UsersService { * @throws ApiError */ public static readUsers({ -skip, -limit = 100, -}: { -skip?: number, -limit?: number, -}): CancelablePromise { + skip, + limit = 100, + }: { + skip?: number, + limit?: number, + }): CancelablePromise { return __request(OpenAPI, { method: 'GET', url: '/api/v1/users/', @@ -50,10 +50,10 @@ limit?: number, * @throws ApiError */ public static createUser({ -requestBody, -}: { -requestBody: UserCreate, -}): CancelablePromise { + requestBody, + }: { + requestBody: UserCreate, + }): CancelablePromise { return __request(OpenAPI, { method: 'POST', url: '/api/v1/users/', @@ -85,10 +85,10 @@ requestBody: UserCreate, * @throws ApiError */ public static updateUserMe({ -requestBody, -}: { -requestBody: UserUpdateMe, -}): CancelablePromise { + requestBody, + }: { + requestBody: UserUpdateMe, + }): CancelablePromise { return __request(OpenAPI, { method: 'PATCH', url: '/api/v1/users/me', @@ -107,10 +107,10 @@ requestBody: UserUpdateMe, * @throws ApiError */ public static updatePasswordMe({ -requestBody, -}: { -requestBody: UpdatePassword, -}): CancelablePromise { + requestBody, + }: { + requestBody: UpdatePassword, + }): CancelablePromise { return __request(OpenAPI, { method: 'PATCH', url: '/api/v1/users/me/password', @@ -123,19 +123,19 @@ requestBody: UpdatePassword, } /** - * Create User Open + * Register User * Create new user without the need to be logged in. * @returns UserOut Successful Response * @throws ApiError */ - public static createUserOpen({ -requestBody, -}: { -requestBody: UserCreateOpen, -}): CancelablePromise { + public static registerUser({ + requestBody, + }: { + requestBody: UserRegister, + }): CancelablePromise { return __request(OpenAPI, { method: 'POST', - url: '/api/v1/users/open', + url: '/api/v1/users/signup', body: requestBody, mediaType: 'application/json', errors: { @@ -151,10 +151,10 @@ requestBody: UserCreateOpen, * @throws ApiError */ public static readUserById({ -userId, -}: { -userId: number, -}): CancelablePromise { + userId, + }: { + userId: number, + }): CancelablePromise { return __request(OpenAPI, { method: 'GET', url: '/api/v1/users/{user_id}', @@ -174,12 +174,12 @@ userId: number, * @throws ApiError */ public static updateUser({ -userId, -requestBody, -}: { -userId: number, -requestBody: UserUpdate, -}): CancelablePromise { + userId, + requestBody, + }: { + userId: number, + requestBody: UserUpdate, + }): CancelablePromise { return __request(OpenAPI, { method: 'PATCH', url: '/api/v1/users/{user_id}', @@ -201,10 +201,10 @@ requestBody: UserUpdate, * @throws ApiError */ public static deleteUser({ -userId, -}: { -userId: number, -}): CancelablePromise { + userId, + }: { + userId: number, + }): CancelablePromise { return __request(OpenAPI, { method: 'DELETE', url: '/api/v1/users/{user_id}', diff --git a/frontend/src/client/services/UtilsService.ts b/frontend/src/client/services/UtilsService.ts index a7ed0bb..bc6f97e 100644 --- a/frontend/src/client/services/UtilsService.ts +++ b/frontend/src/client/services/UtilsService.ts @@ -10,28 +10,6 @@ import { request as __request } from '../core/request'; export class UtilsService { - /** - * Test Celery - * Test Celery worker. - * @returns Message Successful Response - * @throws ApiError - */ - public static testCelery({ -requestBody, -}: { -requestBody: Message, -}): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/api/v1/utils/test-celery/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** * Test Email * Test emails. @@ -39,10 +17,10 @@ requestBody: Message, * @throws ApiError */ public static testEmail({ -emailTo, -}: { -emailTo: string, -}): CancelablePromise { + emailTo, + }: { + emailTo: string, + }): CancelablePromise { return __request(OpenAPI, { method: 'POST', url: '/api/v1/utils/test-email/', diff --git a/frontend/src/components/Admin/AddUser.tsx b/frontend/src/components/Admin/AddUser.tsx index 4ba845f..12fb2ac 100644 --- a/frontend/src/components/Admin/AddUser.tsx +++ b/frontend/src/components/Admin/AddUser.tsx @@ -53,24 +53,23 @@ const AddUser = ({ isOpen, onClose }: AddUserProps) => { }, }) - const addUser = async (data: UserCreate) => { - await UsersService.createUser({ requestBody: data }) - } - - const mutation = useMutation(addUser, { - onSuccess: () => { - showToast("Success!", "User created successfully.", "success") - reset() - onClose() - }, - onError: (err: ApiError) => { - const errDetail = err.body?.detail - showToast("Something went wrong.", `${errDetail}`, "error") + const mutation = useMutation( + (data: UserCreate) => UsersService.createUser({ requestBody: data }), + { + onSuccess: () => { + showToast("Success!", "User created successfully.", "success") + reset() + onClose() + }, + onError: (err: ApiError) => { + const errDetail = err.body?.detail + showToast("Something went wrong.", `${errDetail}`, "error") + }, + onSettled: () => { + queryClient.invalidateQueries("users") + }, }, - onSettled: () => { - queryClient.invalidateQueries("users") - }, - }) + ) const onSubmit: SubmitHandler = (data) => { mutation.mutate(data) diff --git a/frontend/src/components/Admin/EditUser.tsx b/frontend/src/components/Admin/EditUser.tsx index c3f207f..9ac7017 100644 --- a/frontend/src/components/Admin/EditUser.tsx +++ b/frontend/src/components/Admin/EditUser.tsx @@ -52,23 +52,23 @@ const EditUser = ({ user, isOpen, onClose }: EditUserProps) => { defaultValues: user, }) - const updateUser = async (data: UserUpdateForm) => { - await UsersService.updateUser({ userId: user.id, requestBody: data }) - } - - const mutation = useMutation(updateUser, { - onSuccess: () => { - showToast("Success!", "User updated successfully.", "success") - onClose() - }, - onError: (err: ApiError) => { - const errDetail = err.body?.detail - showToast("Something went wrong.", `${errDetail}`, "error") + const mutation = useMutation( + (data: UserUpdateForm) => + UsersService.updateUser({ userId: user.id, requestBody: data }), + { + onSuccess: () => { + showToast("Success!", "User updated successfully.", "success") + onClose() + }, + onError: (err: ApiError) => { + const errDetail = err.body?.detail + showToast("Something went wrong.", `${errDetail}`, "error") + }, + onSettled: () => { + queryClient.invalidateQueries("users") + }, }, - onSettled: () => { - queryClient.invalidateQueries("users") - }, - }) + ) const onSubmit: SubmitHandler = async (data) => { if (data.password === "") { diff --git a/frontend/src/components/Common/Navbar.tsx b/frontend/src/components/Common/Navbar.tsx index 6fcd3a1..edcb3d0 100644 --- a/frontend/src/components/Common/Navbar.tsx +++ b/frontend/src/components/Common/Navbar.tsx @@ -18,7 +18,7 @@ const Navbar = ({ type }: NavbarProps) => { {/* TODO: Complete search functionality */} {/* - + */} diff --git a/frontend/src/components/Common/Sidebar.tsx b/frontend/src/components/Common/Sidebar.tsx index 24a82e9..90a0c06 100644 --- a/frontend/src/components/Common/Sidebar.tsx +++ b/frontend/src/components/Common/Sidebar.tsx @@ -22,8 +22,8 @@ import SidebarItems from "./SidebarItems" const Sidebar = () => { const queryClient = useQueryClient() - const bgColor = useColorModeValue("ui.white", "ui.dark") - const textColor = useColorModeValue("ui.dark", "ui.white") + const bgColor = useColorModeValue("ui.light", "ui.dark") + const textColor = useColorModeValue("ui.dark", "ui.light") const secBgColor = useColorModeValue("ui.secondary", "ui.darkSlate") const currentUser = queryClient.getQueryData("currentUser") const { isOpen, onOpen, onClose } = useDisclosure() diff --git a/frontend/src/components/Common/SidebarItems.tsx b/frontend/src/components/Common/SidebarItems.tsx index d075b09..361318a 100644 --- a/frontend/src/components/Common/SidebarItems.tsx +++ b/frontend/src/components/Common/SidebarItems.tsx @@ -17,7 +17,7 @@ interface SidebarItemsProps { const SidebarItems = ({ onClose }: SidebarItemsProps) => { const queryClient = useQueryClient() - const textColor = useColorModeValue("ui.main", "ui.white") + const textColor = useColorModeValue("ui.main", "ui.light") const bgActive = useColorModeValue("#E2E8F0", "#4A5568") const currentUser = queryClient.getQueryData("currentUser") @@ -25,13 +25,13 @@ const SidebarItems = ({ onClose }: SidebarItemsProps) => { ? [...items, { icon: FiUsers, title: "Admin", path: "/admin" }] : items - const listItems = finalItems.map((item) => ( + const listItems = finalItems.map(({ icon, title, path }) => ( { color={textColor} onClick={onClose} > - - {item.title} + + {title} )) diff --git a/frontend/src/components/Common/UserMenu.tsx b/frontend/src/components/Common/UserMenu.tsx index c767e2f..324dd92 100644 --- a/frontend/src/components/Common/UserMenu.tsx +++ b/frontend/src/components/Common/UserMenu.tsx @@ -6,10 +6,10 @@ import { MenuItem, MenuList, } from "@chakra-ui/react" +import { Link } from "@tanstack/react-router" import { FaUserAstronaut } from "react-icons/fa" import { FiLogOut, FiUser } from "react-icons/fi" -import { Link } from "@tanstack/react-router" import useAuth from "../../hooks/useAuth" const UserMenu = () => { diff --git a/frontend/src/components/Items/AddItem.tsx b/frontend/src/components/Items/AddItem.tsx index be2b9b2..18338ea 100644 --- a/frontend/src/components/Items/AddItem.tsx +++ b/frontend/src/components/Items/AddItem.tsx @@ -40,24 +40,23 @@ const AddItem = ({ isOpen, onClose }: AddItemProps) => { }, }) - const addItem = async (data: ItemCreate) => { - await ItemsService.createItem({ requestBody: data }) - } - - const mutation = useMutation(addItem, { - onSuccess: () => { - showToast("Success!", "Item created successfully.", "success") - reset() - onClose() - }, - onError: (err: ApiError) => { - const errDetail = err.body?.detail - showToast("Something went wrong.", `${errDetail}`, "error") + const mutation = useMutation( + (data: ItemCreate) => ItemsService.createItem({ requestBody: data }), + { + onSuccess: () => { + showToast("Success!", "Item created successfully.", "success") + reset() + onClose() + }, + onError: (err: ApiError) => { + const errDetail = err.body?.detail + showToast("Something went wrong.", `${errDetail}`, "error") + }, + onSettled: () => { + queryClient.invalidateQueries("items") + }, }, - onSettled: () => { - queryClient.invalidateQueries("items") - }, - }) + ) const onSubmit: SubmitHandler = (data) => { mutation.mutate(data) diff --git a/frontend/src/components/Items/EditItem.tsx b/frontend/src/components/Items/EditItem.tsx index b3e3aeb..5d43d50 100644 --- a/frontend/src/components/Items/EditItem.tsx +++ b/frontend/src/components/Items/EditItem.tsx @@ -13,8 +13,8 @@ import { ModalOverlay, } from "@chakra-ui/react" import { type SubmitHandler, useForm } from "react-hook-form" - import { useMutation, useQueryClient } from "react-query" + import { type ApiError, type ItemOut, @@ -43,23 +43,23 @@ const EditItem = ({ item, isOpen, onClose }: EditItemProps) => { defaultValues: item, }) - const updateItem = async (data: ItemUpdate) => { - await ItemsService.updateItem({ id: item.id, requestBody: data }) - } - - const mutation = useMutation(updateItem, { - onSuccess: () => { - showToast("Success!", "Item updated successfully.", "success") - onClose() + const mutation = useMutation( + (data: ItemUpdate) => + ItemsService.updateItem({ id: item.id, requestBody: data }), + { + onSuccess: () => { + showToast("Success!", "Item updated successfully.", "success") + onClose() + }, + onError: (err: ApiError) => { + const errDetail = err.body?.detail + showToast("Something went wrong.", `${errDetail}`, "error") + }, + onSettled: () => { + queryClient.invalidateQueries("items") + }, }, - onError: (err: ApiError) => { - const errDetail = err.body?.detail - showToast("Something went wrong.", `${errDetail}`, "error") - }, - onSettled: () => { - queryClient.invalidateQueries("items") - }, - }) + ) const onSubmit: SubmitHandler = async (data) => { mutation.mutate(data) diff --git a/frontend/src/components/UserSettings/ChangePassword.tsx b/frontend/src/components/UserSettings/ChangePassword.tsx index ffb3ec7..abdc2bb 100644 --- a/frontend/src/components/UserSettings/ChangePassword.tsx +++ b/frontend/src/components/UserSettings/ChangePassword.tsx @@ -14,13 +14,14 @@ import { useMutation } from "react-query" import { type ApiError, type UpdatePassword, UsersService } from "../../client" import useCustomToast from "../../hooks/useCustomToast" +import { confirmPasswordRules, passwordRules } from "../../utils" interface UpdatePasswordForm extends UpdatePassword { confirm_password: string } const ChangePassword = () => { - const color = useColorModeValue("inherit", "ui.white") + const color = useColorModeValue("inherit", "ui.light") const showToast = useCustomToast() const { register, @@ -33,20 +34,20 @@ const ChangePassword = () => { criteriaMode: "all", }) - const UpdatePassword = async (data: UpdatePassword) => { - await UsersService.updatePasswordMe({ requestBody: data }) - } - - const mutation = useMutation(UpdatePassword, { - onSuccess: () => { - showToast("Success!", "Password updated.", "success") - reset() - }, - onError: (err: ApiError) => { - const errDetail = err.body?.detail - showToast("Something went wrong.", `${errDetail}`, "error") + const mutation = useMutation( + (data: UpdatePassword) => + UsersService.updatePasswordMe({ requestBody: data }), + { + onSuccess: () => { + showToast("Success!", "Password updated.", "success") + reset() + }, + onError: (err: ApiError) => { + const errDetail = err.body?.detail + showToast("Something went wrong.", `${errDetail}`, "error") + }, }, - }) + ) const onSubmit: SubmitHandler = async (data) => { mutation.mutate(data) @@ -79,13 +80,7 @@ const ChangePassword = () => { Set Password @@ -97,12 +92,7 @@ const ChangePassword = () => { Confirm Password - value === getValues().new_password || - "The passwords do not match", - })} + {...register("confirm_password", confirmPasswordRules(getValues))} placeholder="Password" type="password" /> diff --git a/frontend/src/components/UserSettings/DeleteConfirmation.tsx b/frontend/src/components/UserSettings/DeleteConfirmation.tsx index db41935..bb1c97e 100644 --- a/frontend/src/components/UserSettings/DeleteConfirmation.tsx +++ b/frontend/src/components/UserSettings/DeleteConfirmation.tsx @@ -31,28 +31,27 @@ const DeleteConfirmation = ({ isOpen, onClose }: DeleteProps) => { const currentUser = queryClient.getQueryData("currentUser") const { logout } = useAuth() - const deleteCurrentUser = async (id: number) => { - await UsersService.deleteUser({ userId: id }) - } - - const mutation = useMutation(deleteCurrentUser, { - onSuccess: () => { - showToast( - "Success", - "Your account has been successfully deleted.", - "success", - ) - logout() - onClose() - }, - onError: (err: ApiError) => { - const errDetail = err.body?.detail - showToast("Something went wrong.", `${errDetail}`, "error") + const mutation = useMutation( + (id: number) => UsersService.deleteUser({ userId: id }), + { + onSuccess: () => { + showToast( + "Success", + "Your account has been successfully deleted.", + "success", + ) + logout() + onClose() + }, + onError: (err: ApiError) => { + const errDetail = err.body?.detail + showToast("Something went wrong.", `${errDetail}`, "error") + }, + onSettled: () => { + queryClient.invalidateQueries("currentUser") + }, }, - onSettled: () => { - queryClient.invalidateQueries("currentUser") - }, - }) + ) const onSubmit = async () => { mutation.mutate(currentUser!.id) diff --git a/frontend/src/components/UserSettings/UserInformation.tsx b/frontend/src/components/UserSettings/UserInformation.tsx index fd13ad5..014f36e 100644 --- a/frontend/src/components/UserSettings/UserInformation.tsx +++ b/frontend/src/components/UserSettings/UserInformation.tsx @@ -27,7 +27,7 @@ import { emailPattern } from "../../utils" const UserInformation = () => { const queryClient = useQueryClient() - const color = useColorModeValue("inherit", "ui.white") + const color = useColorModeValue("inherit", "ui.light") const showToast = useCustomToast() const [editMode, setEditMode] = useState(false) const { user: currentUser } = useAuth() @@ -50,23 +50,22 @@ const UserInformation = () => { setEditMode(!editMode) } - const updateInfo = async (data: UserUpdateMe) => { - await UsersService.updateUserMe({ requestBody: data }) - } - - const mutation = useMutation(updateInfo, { - onSuccess: () => { - showToast("Success!", "User updated successfully.", "success") - }, - onError: (err: ApiError) => { - const errDetail = err.body?.detail - showToast("Something went wrong.", `${errDetail}`, "error") + const mutation = useMutation( + (data: UserUpdateMe) => UsersService.updateUserMe({ requestBody: data }), + { + onSuccess: () => { + showToast("Success!", "User updated successfully.", "success") + }, + onError: (err: ApiError) => { + const errDetail = err.body?.detail + showToast("Something went wrong.", `${errDetail}`, "error") + }, + onSettled: () => { + queryClient.invalidateQueries("users") + queryClient.invalidateQueries("currentUser") + }, }, - onSettled: () => { - queryClient.invalidateQueries("users") - queryClient.invalidateQueries("currentUser") - }, - }) + ) const onSubmit: SubmitHandler = async (data) => { mutation.mutate(data) @@ -99,7 +98,7 @@ const UserInformation = () => { {currentUser?.full_name || "N/A"} diff --git a/frontend/src/hooks/useAuth.ts b/frontend/src/hooks/useAuth.ts index 309a0ab..2abd8d8 100644 --- a/frontend/src/hooks/useAuth.ts +++ b/frontend/src/hooks/useAuth.ts @@ -1,8 +1,10 @@ import { useNavigate } from "@tanstack/react-router" -import { useQuery } from "react-query" +import { useState } from "react" +import { useMutation, useQuery } from "react-query" import { type Body_login_login_access_token as AccessToken, + type ApiError, LoginService, type UserOut, UsersService, @@ -13,6 +15,7 @@ const isLoggedIn = () => { } const useAuth = () => { + const [error, setError] = useState(null) const navigate = useNavigate() const { data: user, isLoading } = useQuery( "currentUser", @@ -27,15 +30,30 @@ const useAuth = () => { formData: data, }) localStorage.setItem("access_token", response.access_token) - navigate({ to: "/" }) } + const loginMutation = useMutation(login, { + onSuccess: () => { + navigate({ to: "/" }) + }, + onError: (err: ApiError) => { + const errDetail = err.body.detail + setError(errDetail) + }, + }) + const logout = () => { localStorage.removeItem("access_token") navigate({ to: "/login" }) } - return { login, logout, user, isLoading } + return { + loginMutation, + logout, + user, + isLoading, + error, + } } export { isLoggedIn } diff --git a/frontend/src/routes/_layout/admin.tsx b/frontend/src/routes/_layout/admin.tsx index 2841bd6..eaf7040 100644 --- a/frontend/src/routes/_layout/admin.tsx +++ b/frontend/src/routes/_layout/admin.tsx @@ -73,7 +73,7 @@ function Admin() { {users.data.map((user) => ( - + {user.full_name || "N/A"} {currentUser?.id === user.id && ( diff --git a/frontend/src/routes/_layout/items.tsx b/frontend/src/routes/_layout/items.tsx index 3326321..1f2f113 100644 --- a/frontend/src/routes/_layout/items.tsx +++ b/frontend/src/routes/_layout/items.tsx @@ -70,7 +70,7 @@ function Items() { {item.id} {item.title} - + {item.description || "N/A"} diff --git a/frontend/src/routes/login.tsx b/frontend/src/routes/login.tsx index 4443e7f..f8df55d 100644 --- a/frontend/src/routes/login.tsx +++ b/frontend/src/routes/login.tsx @@ -18,11 +18,9 @@ import { createFileRoute, redirect, } from "@tanstack/react-router" -import React from "react" import { type SubmitHandler, useForm } from "react-hook-form" import Logo from "../assets/images/fastapi-logo.svg" -import type { ApiError } from "../client" import type { Body_login_login_access_token as AccessToken } from "../client/models/Body_login_login_access_token" import useAuth, { isLoggedIn } from "../hooks/useAuth" import { emailPattern } from "../utils" @@ -40,8 +38,7 @@ export const Route = createFileRoute("/login")({ function Login() { const [show, setShow] = useBoolean() - const { login } = useAuth() - const [error, setError] = React.useState(null) + const { loginMutation, error } = useAuth() const { register, handleSubmit, @@ -56,12 +53,7 @@ function Login() { }) const onSubmit: SubmitHandler = async (data) => { - try { - await login(data) - } catch (err) { - const errDetail = (err as ApiError).body.detail - setError(errDetail) - } + loginMutation.mutate(data) } return ( @@ -105,7 +97,7 @@ function Login() { placeholder="Password" /> Set Password @@ -111,12 +106,7 @@ function ResetPassword() { Confirm Password - value === getValues().new_password || - "The passwords do not match", - })} + {...register("confirm_password", confirmPasswordRules(getValues))} placeholder="Password" type="password" /> diff --git a/frontend/src/theme.tsx b/frontend/src/theme.tsx index 8132e3c..71675dd 100644 --- a/frontend/src/theme.tsx +++ b/frontend/src/theme.tsx @@ -13,9 +13,10 @@ const theme = extendTheme({ secondary: "#EDF2F7", success: "#48BB78", danger: "#E53E3E", - white: "#FFFFFF", + light: "#FAFAFA", dark: "#1A202C", darkSlate: "#252D3D", + dim: "#A0AEC0", }, }, components: { @@ -23,7 +24,7 @@ const theme = extendTheme({ variants: { primary: { backgroundColor: "ui.main", - color: "ui.white", + color: "ui.light", _hover: { backgroundColor: "#00766C", }, @@ -36,7 +37,7 @@ const theme = extendTheme({ }, danger: { backgroundColor: "ui.danger", - color: "ui.white", + color: "ui.light", _hover: { backgroundColor: "#E32727", }, diff --git a/frontend/src/utils.ts b/frontend/src/utils.ts index 1bf5167..ecdee91 100644 --- a/frontend/src/utils.ts +++ b/frontend/src/utils.ts @@ -2,3 +2,34 @@ export const emailPattern = { value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i, message: "Invalid email address", } + +export const passwordRules = (isRequired = true) => { + const rules: any = { + minLength: { + value: 8, + message: "Password must be at least 8 characters", + }, + } + + if (isRequired) { + rules.required = "Password is required" + } + + return rules +} + +export const confirmPasswordRules = ( + getValues: () => any, + isRequired = true, +) => { + const rules: any = { + validate: (value: string) => + value === getValues().password || "The passwords do not match", + } + + if (isRequired) { + rules.required = "Password confirmation is required" + } + + return rules +}