From d158b856cadaeefad9f267376a7d3908460aed9b Mon Sep 17 00:00:00 2001 From: Lukasz Borkowski Date: Sat, 9 Mar 2024 17:16:40 +0100 Subject: [PATCH 01/14] profile screen --- scripts/data/swagger-spec.json | 1369 +++++++++++++++--- src/api/query/articles/articles.ts | 17 +- src/api/query/auth/auth.msw.ts | 26 + src/api/query/auth/auth.ts | 221 ++- src/api/query/users/users.ts | 11 +- src/api/types/authConfirmEmailChangeDto.ts | 13 + src/api/types/authEmailChangeDto.ts | 13 + src/api/types/authUpdateDto.ts | 10 +- src/api/types/errorValidationEntity.ts | 16 + src/api/types/errorValidationEntityErrors.ts | 13 + src/api/types/index.ts | 4 + src/api/types/lastConsentProperties.ts | 2 + src/api/types/updateUserDto.ts | 2 - src/hooks/forms/index.ts | 1 + src/hooks/forms/useUpdateProfileForm.ts | 61 + src/i18n/translations/en.json | 7 +- src/screens/ProfileScreen.tsx | 156 +- 17 files changed, 1679 insertions(+), 263 deletions(-) create mode 100644 src/api/types/authConfirmEmailChangeDto.ts create mode 100644 src/api/types/authEmailChangeDto.ts create mode 100644 src/api/types/errorValidationEntity.ts create mode 100644 src/api/types/errorValidationEntityErrors.ts create mode 100644 src/hooks/forms/useUpdateProfileForm.ts diff --git a/scripts/data/swagger-spec.json b/scripts/data/swagger-spec.json index 0265fe63..ab9e3d5e 100644 --- a/scripts/data/swagger-spec.json +++ b/scripts/data/swagger-spec.json @@ -10,20 +10,42 @@ "requestBody": { "required": true, "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/CreateArticleDto" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateArticleDto" + } + } } }, "responses": { "201": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ArticleEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArticleEntity" + } + } + } + }, + "422": { + "description": "Validation Error - One or more fields did not pass validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorValidationEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -34,8 +56,22 @@ "summary": "Find All Articles", "description": "Retrieves a list of all articles with pagination support.", "parameters": [ - { "name": "page", "required": true, "in": "query", "schema": { "type": "number" } }, - { "name": "pageSize", "required": true, "in": "query", "schema": { "type": "number" } } + { + "name": "page", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "pageSize", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + } ], "responses": { "200": { @@ -44,7 +80,9 @@ "application/json": { "schema": { "type": "array", - "items": { "$ref": "#/components/schemas/ArticleEntity" } + "items": { + "$ref": "#/components/schemas/ArticleEntity" + } } } } @@ -52,7 +90,11 @@ "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -65,8 +107,22 @@ "summary": "Find Draft Articles", "description": "Retrieves a list of draft articles with pagination support.", "parameters": [ - { "name": "page", "required": true, "in": "query", "schema": { "type": "number" } }, - { "name": "pageSize", "required": true, "in": "query", "schema": { "type": "number" } } + { + "name": "page", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "pageSize", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + } ], "responses": { "200": { @@ -75,7 +131,9 @@ "application/json": { "schema": { "type": "array", - "items": { "$ref": "#/components/schemas/ArticleEntity" } + "items": { + "$ref": "#/components/schemas/ArticleEntity" + } } } } @@ -83,7 +141,11 @@ "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -96,19 +158,34 @@ "summary": "Find Article by ID", "description": "Retrieves an article by its unique identifier.", "parameters": [ - { "name": "id", "required": true, "in": "path", "schema": { "type": "number" } } + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } ], "responses": { "200": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ArticleEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArticleEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -119,25 +196,54 @@ "summary": "Update Article", "description": "Updates an article with the provided details.", "parameters": [ - { "name": "id", "required": true, "in": "path", "schema": { "type": "number" } } + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } ], "requestBody": { "required": true, "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/UpdateArticleDto" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateArticleDto" + } + } } }, "responses": { "201": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ArticleEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArticleEntity" + } + } + } + }, + "422": { + "description": "Validation Error - One or more fields did not pass validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorValidationEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -148,14 +254,27 @@ "summary": "Remove Article", "description": "Deletes an article by its unique identifier.", "parameters": [ - { "name": "id", "required": true, "in": "path", "schema": { "type": "number" } } + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } ], "responses": { - "204": { "description": "" }, + "204": { + "description": "" + }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -171,47 +290,93 @@ "requestBody": { "required": true, "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/CreateUserDto" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateUserDto" + } + } } }, "responses": { "201": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/UserEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserEntity" + } + } } }, "401": { "description": "Unauthorized", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, "403": { "description": "Forbidden", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } + } + }, + "422": { + "description": "Validation Error - One or more fields did not pass validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorValidationEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, "tags": ["users"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] }, "get": { "operationId": "UsersController_findAll", "summary": "Find All Users", "description": "Retrieves a list of all users.", "parameters": [ - { "name": "page", "required": true, "in": "query", "schema": { "type": "number" } }, - { "name": "pageSize", "required": true, "in": "query", "schema": { "type": "number" } } + { + "name": "page", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "pageSize", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + } ], "responses": { "200": { @@ -220,7 +385,9 @@ "application/json": { "schema": { "type": "array", - "items": { "$ref": "#/components/schemas/UserEntity" } + "items": { + "$ref": "#/components/schemas/UserEntity" + } } } } @@ -229,25 +396,39 @@ "description": "Unauthorized", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, "403": { "description": "Forbidden", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, "tags": ["users"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] } }, "/api/v1/users/{id}": { @@ -256,120 +437,199 @@ "summary": "Find User by ID", "description": "Retrieves a user by its ID.", "parameters": [ - { "name": "id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } ], "responses": { "200": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/UserEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserEntity" + } + } } }, "401": { "description": "Unauthorized", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, "403": { "description": "Forbidden", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, "tags": ["users"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] }, "patch": { "operationId": "UsersController_update", "summary": "Update User", "description": "Updates a user with the provided details.", "parameters": [ - { "name": "id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } ], "requestBody": { "required": true, "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/UpdateUserDto" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateUserDto" + } + } } }, "responses": { "201": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/UserEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserEntity" + } + } } }, "401": { "description": "Unauthorized", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, "403": { "description": "Forbidden", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, "tags": ["users"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] }, "delete": { "operationId": "UsersController_remove", "summary": "Remove User", "description": "Deletes a user by their unique identifier.", "parameters": [ - { "name": "id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } ], "responses": { "200": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/UserEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserEntity" + } + } } }, "401": { "description": "Unauthorized", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, "403": { "description": "Forbidden", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, "tags": ["users"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] } }, "/api/v1/auth/email/login": { @@ -381,42 +641,72 @@ "requestBody": { "required": true, "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/AuthEmailLoginDto" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthEmailLoginDto" + } + } } }, "responses": { "201": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/AuthEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthEntity" + } + } } }, "401": { "description": "Unauthorized - Invalid credentials", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, "403": { "description": "Please activate your account before proceeding", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } + } + }, + "422": { + "description": "Validation Error - One or more fields did not pass validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorValidationEntity" + } + } } }, "429": { "description": "ThrottlerException: Too Many Requests", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" + } } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -434,14 +724,18 @@ "in": "header", "description": "Specifies the preferred language for API responses. Supported values are: en (English), de (German), pl (Polish)", "required": false, - "schema": { "type": "string" } + "schema": { + "type": "string" + } } ], "requestBody": { "required": true, "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/AuthRegisterLoginDto" } + "schema": { + "$ref": "#/components/schemas/AuthRegisterLoginDto" + } } } }, @@ -449,22 +743,44 @@ "201": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/UserEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserEntity" + } + } + } + }, + "400": { + "description": "Bad Request - Missing or invalid registration details" + }, + "422": { + "description": "Validation Error - One or more fields did not pass validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorValidationEntity" + } + } } }, - "400": { "description": "Bad Request - Missing or invalid registration details" }, "429": { "description": "ThrottlerException: Too Many Requests", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" + } } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -482,29 +798,53 @@ "in": "header", "description": "Specifies the preferred language for API responses. Supported values are: en (English), de (German), pl (Polish)", "required": false, - "schema": { "type": "string" } + "schema": { + "type": "string" + } } ], "requestBody": { "required": true, "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/AuthConfirmEmailDto" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthConfirmEmailDto" + } + } } }, "responses": { - "400": { "description": "Bad Request - Invalid or expired hash code" }, + "400": { + "description": "Bad Request - Invalid or expired hash code" + }, + "422": { + "description": "Validation Error - One or more fields did not pass validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorValidationEntity" + } + } + } + }, "429": { "description": "ThrottlerException: Too Many Requests", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" + } } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -522,14 +862,18 @@ "in": "header", "description": "Specifies the preferred language for API responses. Supported values are: en (English), de (German), pl (Polish)", "required": false, - "schema": { "type": "string" } + "schema": { + "type": "string" + } } ], "requestBody": { "required": true, "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/AuthResendVerificationEmailDto" } + "schema": { + "$ref": "#/components/schemas/AuthResendVerificationEmailDto" + } } } }, @@ -537,21 +881,41 @@ "400": { "description": "Bad Request - Invalid email format", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } + } + }, + "422": { + "description": "Validation Error - One or more fields did not pass validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorValidationEntity" + } + } } }, "429": { "description": "ThrottlerException: Too Many Requests", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" + } } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -569,14 +933,18 @@ "in": "header", "description": "Specifies the preferred language for API responses. Supported values are: en (English), de (German), pl (Polish)", "required": false, - "schema": { "type": "string" } + "schema": { + "type": "string" + } } ], "requestBody": { "required": true, "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/AuthForgotPasswordDto" } + "schema": { + "$ref": "#/components/schemas/AuthForgotPasswordDto" + } } } }, @@ -584,21 +952,41 @@ "400": { "description": "Bad Request - Invalid email format", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } + } + }, + "422": { + "description": "Validation Error - One or more fields did not pass validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorValidationEntity" + } + } } }, "429": { "description": "ThrottlerException: Too Many Requests", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" + } } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -615,7 +1003,9 @@ "required": true, "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/AuthResetPasswordDto" } + "schema": { + "$ref": "#/components/schemas/AuthResetPasswordDto" + } } } }, @@ -623,21 +1013,173 @@ "400": { "description": "Bad Request - Invalid or expired hash code", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } + } + }, + "422": { + "description": "Validation Error - One or more fields did not pass validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorValidationEntity" + } + } } }, "429": { "description": "ThrottlerException: Too Many Requests", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" + } } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } + } + } + }, + "tags": ["auth"] + } + }, + "/api/v1/auth/email/change": { + "post": { + "operationId": "AuthController_emailChange", + "summary": "Initialize Email Change", + "description": "Initiates the process to change the user's email address. After initialization, the user must confirm the email address change through another endpoint.", + "parameters": [ + { + "name": "Accept-Language", + "in": "header", + "description": "Specifies the preferred language for API responses. Supported values are: en (English), de (German), pl (Polish)", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthEmailChangeDto" + } + } + } + }, + "responses": { + "400": { + "description": "Bad Request - Invalid or expired hash code", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } + } + }, + "422": { + "description": "Validation Error - One or more fields did not pass validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorValidationEntity" + } + } + } + }, + "429": { + "description": "ThrottlerException: Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } + } + } + }, + "tags": ["auth"] + } + }, + "/api/v1/auth/email/change-confirm": { + "post": { + "operationId": "AuthController_confirmEmailChange", + "summary": "Confirm Email Change", + "description": "Confirms the change of a user's email address using a verification code sent to the new email. This endpoint validates the verification code (hash) received by the user to complete the email address change process.", + "parameters": [ + { + "name": "Accept-Language", + "in": "header", + "description": "Specifies the preferred language for API responses. Supported values are: en (English), de (German), pl (Polish)", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthConfirmEmailChangeDto" + } + } + } + }, + "responses": { + "400": { + "description": "Bad Request - Invalid or expired hash code", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } + } + }, + "429": { + "description": "ThrottlerException: Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorTooManyRequestsEntity" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -654,26 +1196,40 @@ "201": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/UserEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserEntity" + } + } } }, "401": { "description": "Unauthorized", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, "tags": ["auth"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] }, "patch": { "operationId": "AuthController_update", @@ -683,7 +1239,11 @@ "requestBody": { "required": true, "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/AuthUpdateDto" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthUpdateDto" + } + } } }, "responses": { @@ -691,26 +1251,42 @@ "description": "Unauthorized", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, - "404": { "description": "User not found" }, + "404": { + "description": "User not found" + }, "422": { "description": "Missing old password / Incorrect old password / Missing password", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, "tags": ["auth"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] }, "delete": { "operationId": "AuthController_delete", @@ -722,19 +1298,29 @@ "description": "Unauthorized", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, "tags": ["auth"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] } }, "/api/v1/auth/refresh": { @@ -747,26 +1333,40 @@ "201": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/RefreshEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefreshEntity" + } + } } }, "401": { "description": "Unauthorized", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, "tags": ["auth"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] } }, "/api/v1/auth/logout": { @@ -780,19 +1380,29 @@ "description": "Unauthorized", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, "tags": ["auth"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] } }, "/api/v1/auth/logout/all": { @@ -806,19 +1416,29 @@ "description": "Unauthorized", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorUnauthorizedEntity" } + "schema": { + "$ref": "#/components/schemas/ErrorUnauthorizedEntity" + } } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, "tags": ["auth"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] } }, "/api/v1/files/upload": { @@ -834,8 +1454,13 @@ "schema": { "type": "object", "properties": { - "file": { "type": "string", "format": "binary" }, - "category": { "type": "string" } + "file": { + "type": "string", + "format": "binary" + }, + "category": { + "type": "string" + } } } } @@ -845,14 +1470,26 @@ "201": { "description": "", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/FileEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/FileEntity" + } + } } }, - "422": { "description": "Unprocessable Entity - No file selected or missing user ID." }, - "500": { "description": "Internal server error" } + "422": { + "description": "Unprocessable Entity - No file selected or missing user ID." + }, + "500": { + "description": "Internal server error" + } }, "tags": ["files"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] } }, "/api/v1/files/{fileName}": { @@ -861,32 +1498,58 @@ "summary": "Download File", "description": "Downloads the specified file.", "parameters": [ - { "name": "fileName", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "fileName", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } ], "responses": { "403": { "description": "Forbidden - You do not have permission to view this file or file does not exist." }, - "500": { "description": "Internal server error" } + "500": { + "description": "Internal server error" + } }, "tags": ["files"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] }, "delete": { "operationId": "FilesController_deleteFile", "summary": "Delete File", "description": "Deletes the specified file.", "parameters": [ - { "name": "fileName", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "fileName", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } ], "responses": { "403": { "description": "Forbidden - You do not have permission to delete this file or file does not exist." }, - "500": { "description": "Internal server error" } + "500": { + "description": "Internal server error" + } }, "tags": ["files"], - "security": [{ "bearer": [] }] + "security": [ + { + "bearer": [] + } + ] } }, "/api/v1/auth/google/login": { @@ -898,32 +1561,52 @@ "requestBody": { "required": true, "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/AuthGoogleLoginDto" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthGoogleLoginDto" + } + } } }, "responses": { "201": { "description": "Successfully logged in with Google", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/AuthEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthEntity" + } + } } }, "400": { "description": "Bad Request - Error during Google token verification or processing", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, "422": { "description": "Unprocessable Entity - Invalid or expired Google token", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -940,7 +1623,9 @@ "required": true, "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/AuthFacebookLoginDto" } + "schema": { + "$ref": "#/components/schemas/AuthFacebookLoginDto" + } } } }, @@ -948,25 +1633,41 @@ "201": { "description": "Successfully logged in with Facebook", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/AuthEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthEntity" + } + } } }, "400": { "description": "Bad Request - Error during Facebook token verification or processing", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, "422": { "description": "Unprocessable Entity - Invalid or expired Facebook token", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -982,32 +1683,52 @@ "requestBody": { "required": true, "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/AuthAppleLoginDto" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthAppleLoginDto" + } + } } }, "responses": { "201": { "description": "Successfully logged in with Apple", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/AuthEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthEntity" + } + } } }, "400": { "description": "Bad Request - Error during Apple token verification or processing", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, "422": { "description": "Unprocessable Entity - Invalid or expired Apple token", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorServerEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorServerEntity" + } + } } } }, @@ -1024,16 +1745,26 @@ "200": { "description": "The health check result.", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/HealthEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/HealthEntity" + } + } } }, "500": { "description": "Internal server error", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEntity" } } + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEntity" + } + } } }, - "503": { "description": "One or more health checks failed" } + "503": { + "description": "One or more health checks failed" + } }, "tags": ["health"] } @@ -1050,18 +1781,24 @@ } }, "tags": [], - "servers": [ - { "url": "undefined", "description": "Local environment" }, - { "url": "https://production.api.com/", "description": "Production" }, - { "url": "https://staging.api.com/", "description": "Staging" } - ], + "servers": [], "components": { - "securitySchemes": { "bearer": { "scheme": "bearer", "bearerFormat": "JWT", "type": "http" } }, + "securitySchemes": { + "bearer": { + "scheme": "bearer", + "bearerFormat": "JWT", + "type": "http" + } + }, "schemas": { "ErrorServerEntity": { "type": "object", "properties": { - "error": { "type": "string", "description": "Type of error", "example": "Server Error" }, + "error": { + "type": "string", + "description": "Type of error", + "example": "Server Error" + }, "statusCode": { "type": "number", "description": "HTTP status code indicating the error", @@ -1073,35 +1810,75 @@ "CreateArticleDto": { "type": "object", "properties": { - "title": { "type": "string" }, - "description": { "type": "string" }, - "body": { "type": "string" }, - "published": { "type": "boolean", "default": false } + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "body": { + "type": "string" + }, + "published": { + "type": "boolean", + "default": false + } }, "required": ["title", "body"] }, "AuthorPublicDto": { "type": "object", "properties": { - "email": { "type": "string" }, - "firstName": { "type": "string" }, - "lastName": { "type": "string" } + "email": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + } }, "required": ["email", "firstName", "lastName"] }, "ArticleEntity": { "type": "object", "properties": { - "id": { "type": "number" }, - "title": { "type": "string" }, - "description": { "type": "string", "nullable": true }, - "body": { "type": "string" }, - "published": { "type": "boolean" }, - "createdAt": { "format": "date-time", "type": "string" }, - "updatedAt": { "format": "date-time", "type": "string" }, - "deletedAt": { "format": "date-time", "type": "string" }, - "authorId": { "type": "string", "nullable": true }, - "author": { "$ref": "#/components/schemas/AuthorPublicDto" } + "id": { + "type": "number" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "body": { + "type": "string" + }, + "published": { + "type": "boolean" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "authorId": { + "type": "string", + "nullable": true + }, + "author": { + "$ref": "#/components/schemas/AuthorPublicDto" + } }, "required": [ "id", @@ -1114,19 +1891,53 @@ "author" ] }, + "ErrorValidationEntity": { + "type": "object", + "properties": { + "status": { + "type": "number", + "description": "HTTP status code indicating the error", + "example": 422 + }, + "errors": { + "type": "object", + "description": "Object containing field-specific validation errors", + "example": { + "email": "Invalid email format." + }, + "additionalProperties": { + "type": "string" + } + } + }, + "required": ["status", "errors"] + }, "UpdateArticleDto": { "type": "object", "properties": { - "title": { "type": "string" }, - "description": { "type": "string" }, - "body": { "type": "string" }, - "published": { "type": "boolean", "default": false } + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "body": { + "type": "string" + }, + "published": { + "type": "boolean", + "default": false + } } }, "ErrorUnauthorizedEntity": { "type": "object", "properties": { - "error": { "type": "string", "description": "Type of error", "example": "Unauthorized" }, + "error": { + "type": "string", + "description": "Type of error", + "example": "Unauthorized" + }, "statusCode": { "type": "number", "description": "HTTP status code indicating the error", @@ -1143,7 +1954,11 @@ "description": "Message describing the error", "example": "An error occurred while processing your request" }, - "error": { "type": "string", "description": "Type of error", "example": "Forbidden" }, + "error": { + "type": "string", + "description": "Type of error", + "example": "Forbidden" + }, "statusCode": { "type": "number", "description": "HTTP status code indicating the error", @@ -1204,11 +2019,19 @@ }, "role": { "description": "The role assigned to the user.", - "allOf": [{ "$ref": "#/components/schemas/RoleDto" }] + "allOf": [ + { + "$ref": "#/components/schemas/RoleDto" + } + ] }, "status": { "description": "The status of the user account.", - "allOf": [{ "$ref": "#/components/schemas/StatusDto" }] + "allOf": [ + { + "$ref": "#/components/schemas/StatusDto" + } + ] } }, "required": ["email", "password", "firstName", "lastName", "locale", "role", "status"] @@ -1270,8 +2093,18 @@ "example": "1.0", "description": "Version of privacy policy." }, - "createdAt": { "format": "date-time", "type": "string" }, - "updatedAt": { "format": "date-time", "type": "string" } + "createdAt": { + "format": "date-time", + "type": "string", + "example": "2023-01-01T00:00:00.000Z", + "description": "The date and time when the consents were last created or the user agreed to the terms for the first time." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "example": "2023-01-02T00:00:00.000Z", + "description": "The date and time of the last update to the consents, indicating when the user last modified their agreement or the consents were refreshed." + } }, "required": [ "termsAccepted", @@ -1285,7 +2118,10 @@ "UserEntity": { "type": "object", "properties": { - "id": { "type": "string", "example": "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8" }, + "id": { + "type": "string", + "example": "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8" + }, "createdAt": { "format": "date-time", "type": "string", @@ -1296,24 +2132,67 @@ "type": "string", "example": "2022-02-01T00:00:00.000Z" }, - "deletedAt": { "format": "date-time", "type": "string", "example": null }, - "email": { "type": "string", "example": "user@example.com" }, - "firstName": { "type": "string", "example": "John" }, - "lastName": { "type": "string", "example": "Doe" }, - "provider": { "type": "string", "example": "google" }, - "socialId": { "type": "string", "example": "102209777480561953757" }, - "locale": { "type": "string", "example": "en-US" }, + "deletedAt": { + "format": "date-time", + "type": "string", + "example": null + }, + "email": { + "type": "string", + "example": "user@example.com" + }, + "firstName": { + "type": "string", + "example": "John" + }, + "lastName": { + "type": "string", + "example": "Doe" + }, + "provider": { + "type": "string", + "example": "google" + }, + "socialId": { + "type": "string", + "example": "102209777480561953757" + }, + "locale": { + "type": "string", + "example": "en-US" + }, "role": { - "example": { "id": 2, "name": "USER" }, - "allOf": [{ "$ref": "#/components/schemas/Role" }] + "example": { + "id": 2, + "name": "USER" + }, + "allOf": [ + { + "$ref": "#/components/schemas/Role" + } + ] }, "status": { - "example": { "id": 1, "name": "ACTIVE" }, - "allOf": [{ "$ref": "#/components/schemas/Status" }] + "example": { + "id": 1, + "name": "ACTIVE" + }, + "allOf": [ + { + "$ref": "#/components/schemas/Status" + } + ] }, "consent": { - "example": { "termsAccepted": true, "privacyPolicyAccepted": true }, - "allOf": [{ "$ref": "#/components/schemas/LastConsentProperties" }] + "example": { + "termsAccepted": true, + "privacyPolicyAccepted": true + }, + "allOf": [ + { + "$ref": "#/components/schemas/LastConsentProperties" + } + ] } }, "required": [ @@ -1361,11 +2240,19 @@ }, "role": { "description": "The updated role assigned to the user.", - "allOf": [{ "$ref": "#/components/schemas/RoleDto" }] + "allOf": [ + { + "$ref": "#/components/schemas/RoleDto" + } + ] }, "status": { "description": "The updated status of the user account.", - "allOf": [{ "$ref": "#/components/schemas/StatusDto" }] + "allOf": [ + { + "$ref": "#/components/schemas/StatusDto" + } + ] }, "provider": { "type": "string", @@ -1374,13 +2261,9 @@ "socialId": { "type": "string", "description": "The social ID associated with the user account." - }, - "hash": { - "type": "string", - "description": "The updated hash associated with the user account." } }, - "required": ["provider", "socialId", "hash"] + "required": ["provider", "socialId"] }, "AuthEmailLoginDto": { "type": "object", @@ -1418,7 +2301,11 @@ }, "user": { "description": "The user entity associated with the authentication.", - "allOf": [{ "$ref": "#/components/schemas/UserEntity" }] + "allOf": [ + { + "$ref": "#/components/schemas/UserEntity" + } + ] } }, "required": ["accessToken", "refreshToken", "tokenExpires", "user"] @@ -1442,17 +2329,35 @@ "AuthRegisterLoginDto": { "type": "object", "properties": { - "email": { "type": "string", "example": "example@binarapps.com" }, - "password": { "type": "string", "example": "NewSecurePassword123!" }, - "firstName": { "type": "string", "example": "Jon" }, - "lastName": { "type": "string", "example": "Doe" }, + "email": { + "type": "string", + "example": "example@binarapps.com" + }, + "password": { + "type": "string", + "example": "NewSecurePassword123!" + }, + "firstName": { + "type": "string", + "example": "Jon" + }, + "lastName": { + "type": "string", + "example": "Doe" + }, "locale": { "type": "string", "example": "en-US", "description": "IETF language tags (e.g., en-US)." }, - "termsAccepted": { "type": "boolean", "example": true }, - "privacyPolicyAccepted": { "type": "boolean", "example": true } + "termsAccepted": { + "type": "boolean", + "example": true + }, + "privacyPolicyAccepted": { + "type": "boolean", + "example": true + } }, "required": [ "email", @@ -1513,6 +2418,28 @@ }, "required": ["password", "hash"] }, + "AuthEmailChangeDto": { + "type": "object", + "properties": { + "email": { + "type": "string", + "example": "example@binarapps.com", + "description": "The email address associated with the user account." + } + }, + "required": ["email"] + }, + "AuthConfirmEmailChangeDto": { + "type": "object", + "properties": { + "hash": { + "type": "string", + "example": "a1b2c3d4e5f6g7h8i9j0", + "description": "The confirmation hash received in the email." + } + }, + "required": ["hash"] + }, "AuthUpdateDto": { "type": "object", "properties": { @@ -1541,8 +2468,7 @@ "example": "OldSecurePassword123!", "description": "The old password required for security verification when updating user credentials." } - }, - "required": ["firstName", "lastName", "locale", "password", "oldPassword"] + } }, "RefreshEntity": { "type": "object", @@ -1672,15 +2598,27 @@ "properties": { "db": { "description": "The status of the database connection", - "allOf": [{ "$ref": "#/components/schemas/HealthCheckStatusDto" }] + "allOf": [ + { + "$ref": "#/components/schemas/HealthCheckStatusDto" + } + ] }, "domain": { "description": "The status of the domain", - "allOf": [{ "$ref": "#/components/schemas/HealthCheckStatusDto" }] + "allOf": [ + { + "$ref": "#/components/schemas/HealthCheckStatusDto" + } + ] }, "cache": { "description": "The status of the cache", - "allOf": [{ "$ref": "#/components/schemas/HealthCheckStatusDto" }] + "allOf": [ + { + "$ref": "#/components/schemas/HealthCheckStatusDto" + } + ] } }, "required": ["db", "domain", "cache"] @@ -1688,10 +2626,18 @@ "HealthEntity": { "type": "object", "properties": { - "status": { "type": "string", "description": "Overall health status", "example": "ok" }, + "status": { + "type": "string", + "description": "Overall health status", + "example": "ok" + }, "info": { "description": "Detailed info about each component's health", - "allOf": [{ "$ref": "#/components/schemas/HealthCheckInfoDto" }] + "allOf": [ + { + "$ref": "#/components/schemas/HealthCheckInfoDto" + } + ] }, "error": { "type": "object", @@ -1700,12 +2646,19 @@ }, "details": { "description": "Detailed health check results for each component", - "allOf": [{ "$ref": "#/components/schemas/HealthCheckInfoDto" }] + "allOf": [ + { + "$ref": "#/components/schemas/HealthCheckInfoDto" + } + ] } }, "required": ["status", "info", "error", "details"] } } }, - "externalDocs": { "description": "JSON", "url": "/docs-json" } + "externalDocs": { + "description": "JSON", + "url": "/docs-json" + } } diff --git a/src/api/query/articles/articles.ts b/src/api/query/articles/articles.ts index 6c02cc4b..f905a8f1 100644 --- a/src/api/query/articles/articles.ts +++ b/src/api/query/articles/articles.ts @@ -24,6 +24,7 @@ import type { ArticlesControllerFindDraftsParams, CreateArticleDto, ErrorServerEntity, + ErrorValidationEntity, UpdateArticleDto, } from '../../types' @@ -49,7 +50,7 @@ export const articlesControllerCreate = ( } export const getArticlesControllerCreateMutationOptions = < - TError = ErrorType, + TError = ErrorType, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -83,13 +84,15 @@ export type ArticlesControllerCreateMutationResult = NonNullable< Awaited> > export type ArticlesControllerCreateMutationBody = BodyType -export type ArticlesControllerCreateMutationError = ErrorType +export type ArticlesControllerCreateMutationError = ErrorType< + ErrorValidationEntity | ErrorServerEntity +> /** * @summary Create Article */ export const useArticlesControllerCreate = < - TError = ErrorType, + TError = ErrorType, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -340,7 +343,7 @@ export const articlesControllerUpdate = ( } export const getArticlesControllerUpdateMutationOptions = < - TError = ErrorType, + TError = ErrorType, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -374,13 +377,15 @@ export type ArticlesControllerUpdateMutationResult = NonNullable< Awaited> > export type ArticlesControllerUpdateMutationBody = BodyType -export type ArticlesControllerUpdateMutationError = ErrorType +export type ArticlesControllerUpdateMutationError = ErrorType< + ErrorValidationEntity | ErrorServerEntity +> /** * @summary Update Article */ export const useArticlesControllerUpdate = < - TError = ErrorType, + TError = ErrorType, TContext = unknown >(options?: { mutation?: UseMutationOptions< diff --git a/src/api/query/auth/auth.msw.ts b/src/api/query/auth/auth.msw.ts index 2eade02d..398ac953 100644 --- a/src/api/query/auth/auth.msw.ts +++ b/src/api/query/auth/auth.msw.ts @@ -212,6 +212,30 @@ export const getAuthControllerResetPasswordMockHandler = () => { }) } +export const getAuthControllerEmailChangeMockHandler = () => { + return http.post('*/api/v1/auth/email/change', async () => { + await delay(1000) + return new HttpResponse(null, { + status: 200, + headers: { + 'Content-Type': 'application/json', + }, + }) + }) +} + +export const getAuthControllerConfirmEmailChangeMockHandler = () => { + return http.post('*/api/v1/auth/email/change-confirm', async () => { + await delay(1000) + return new HttpResponse(null, { + status: 200, + headers: { + 'Content-Type': 'application/json', + }, + }) + }) +} + export const getAuthControllerMeMockHandler = (overrideResponse?: UserEntity) => { return http.get('*/api/v1/auth/me', async () => { await delay(1000) @@ -296,6 +320,8 @@ export const getAuthMock = () => [ getAuthControllerResendVerificationEmailMockHandler(), getAuthControllerForgotPasswordMockHandler(), getAuthControllerResetPasswordMockHandler(), + getAuthControllerEmailChangeMockHandler(), + getAuthControllerConfirmEmailChangeMockHandler(), getAuthControllerMeMockHandler(), getAuthControllerUpdateMockHandler(), getAuthControllerDeleteMockHandler(), diff --git a/src/api/query/auth/auth.ts b/src/api/query/auth/auth.ts index 3c5e2f98..cb0b353a 100644 --- a/src/api/query/auth/auth.ts +++ b/src/api/query/auth/auth.ts @@ -19,7 +19,9 @@ import type { import { customInstance } from '../../axios/custom-instance' import type { ErrorType, BodyType } from '../../axios/custom-instance' import type { + AuthConfirmEmailChangeDto, AuthConfirmEmailDto, + AuthEmailChangeDto, AuthEmailLoginDto, AuthEntity, AuthForgotPasswordDto, @@ -31,6 +33,7 @@ import type { ErrorServerEntity, ErrorTooManyRequestsEntity, ErrorUnauthorizedEntity, + ErrorValidationEntity, RefreshEntity, UserEntity, } from '../../types' @@ -58,7 +61,11 @@ export const authControllerLogin = ( export const getAuthControllerLoginMutationOptions = < TError = ErrorType< - ErrorUnauthorizedEntity | ErrorEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + | ErrorUnauthorizedEntity + | ErrorEntity + | ErrorValidationEntity + | ErrorTooManyRequestsEntity + | ErrorServerEntity >, TContext = unknown >(options?: { @@ -94,7 +101,11 @@ export type AuthControllerLoginMutationResult = NonNullable< > export type AuthControllerLoginMutationBody = BodyType export type AuthControllerLoginMutationError = ErrorType< - ErrorUnauthorizedEntity | ErrorEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + | ErrorUnauthorizedEntity + | ErrorEntity + | ErrorValidationEntity + | ErrorTooManyRequestsEntity + | ErrorServerEntity > /** @@ -102,7 +113,11 @@ export type AuthControllerLoginMutationError = ErrorType< */ export const useAuthControllerLogin = < TError = ErrorType< - ErrorUnauthorizedEntity | ErrorEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + | ErrorUnauthorizedEntity + | ErrorEntity + | ErrorValidationEntity + | ErrorTooManyRequestsEntity + | ErrorServerEntity >, TContext = unknown >(options?: { @@ -138,7 +153,7 @@ export const authControllerRegister = ( } export const getAuthControllerRegisterMutationOptions = < - TError = ErrorType, + TError = ErrorType, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -173,14 +188,14 @@ export type AuthControllerRegisterMutationResult = NonNullable< > export type AuthControllerRegisterMutationBody = BodyType export type AuthControllerRegisterMutationError = ErrorType< - void | ErrorTooManyRequestsEntity | ErrorServerEntity + void | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity > /** * @summary User Registration */ export const useAuthControllerRegister = < - TError = ErrorType, + TError = ErrorType, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -215,7 +230,7 @@ export const authControllerConfirmEmail = ( } export const getAuthControllerConfirmEmailMutationOptions = < - TError = ErrorType, + TError = ErrorType, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -250,14 +265,14 @@ export type AuthControllerConfirmEmailMutationResult = NonNullable< > export type AuthControllerConfirmEmailMutationBody = BodyType export type AuthControllerConfirmEmailMutationError = ErrorType< - void | ErrorTooManyRequestsEntity | ErrorServerEntity + void | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity > /** * @summary Confirm Email */ export const useAuthControllerConfirmEmail = < - TError = ErrorType, + TError = ErrorType, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -292,7 +307,9 @@ export const authControllerResendVerificationEmail = ( } export const getAuthControllerResendVerificationEmailMutationOptions = < - TError = ErrorType, + TError = ErrorType< + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + >, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -328,14 +345,16 @@ export type AuthControllerResendVerificationEmailMutationResult = NonNullable< export type AuthControllerResendVerificationEmailMutationBody = BodyType export type AuthControllerResendVerificationEmailMutationError = ErrorType< - ErrorEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity > /** * @summary Resend Verification Email */ export const useAuthControllerResendVerificationEmail = < - TError = ErrorType, + TError = ErrorType< + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + >, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -370,7 +389,9 @@ export const authControllerForgotPassword = ( } export const getAuthControllerForgotPasswordMutationOptions = < - TError = ErrorType, + TError = ErrorType< + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + >, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -405,14 +426,16 @@ export type AuthControllerForgotPasswordMutationResult = NonNullable< > export type AuthControllerForgotPasswordMutationBody = BodyType export type AuthControllerForgotPasswordMutationError = ErrorType< - ErrorEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity > /** * @summary Forgot Password */ export const useAuthControllerForgotPassword = < - TError = ErrorType, + TError = ErrorType< + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + >, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -447,7 +470,9 @@ export const authControllerResetPassword = ( } export const getAuthControllerResetPasswordMutationOptions = < - TError = ErrorType, + TError = ErrorType< + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + >, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -482,14 +507,16 @@ export type AuthControllerResetPasswordMutationResult = NonNullable< > export type AuthControllerResetPasswordMutationBody = BodyType export type AuthControllerResetPasswordMutationError = ErrorType< - ErrorEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity > /** * @summary Reset Password */ export const useAuthControllerResetPassword = < - TError = ErrorType, + TError = ErrorType< + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + >, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -504,6 +531,164 @@ export const useAuthControllerResetPassword = < return useMutation(mutationOptions) } +/** + * Initiates the process to change the user's email address. After initialization, the user must confirm the email address change through another endpoint. + * @summary Initialize Email Change + */ +export const authControllerEmailChange = ( + authEmailChangeDto: BodyType, + options?: SecondParameter +) => { + return customInstance( + { + url: `/api/v1/auth/email/change`, + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + data: authEmailChangeDto, + }, + options + ) +} + +export const getAuthControllerEmailChangeMutationOptions = < + TError = ErrorType< + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + >, + TContext = unknown +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { data: BodyType }, + TContext + > + request?: SecondParameter +}): UseMutationOptions< + Awaited>, + TError, + { data: BodyType }, + TContext +> => { + const { mutation: mutationOptions, request: requestOptions } = options ?? {} + + const mutationFn: MutationFunction< + Awaited>, + { data: BodyType } + > = (props) => { + const { data } = props ?? {} + + return authControllerEmailChange(data, requestOptions) + } + + return { mutationFn, ...mutationOptions } +} + +export type AuthControllerEmailChangeMutationResult = NonNullable< + Awaited> +> +export type AuthControllerEmailChangeMutationBody = BodyType +export type AuthControllerEmailChangeMutationError = ErrorType< + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity +> + +/** + * @summary Initialize Email Change + */ +export const useAuthControllerEmailChange = < + TError = ErrorType< + ErrorEntity | ErrorValidationEntity | ErrorTooManyRequestsEntity | ErrorServerEntity + >, + TContext = unknown +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { data: BodyType }, + TContext + > + request?: SecondParameter +}) => { + const mutationOptions = getAuthControllerEmailChangeMutationOptions(options) + + return useMutation(mutationOptions) +} +/** + * Confirms the change of a user's email address using a verification code sent to the new email. This endpoint validates the verification code (hash) received by the user to complete the email address change process. + * @summary Confirm Email Change + */ +export const authControllerConfirmEmailChange = ( + authConfirmEmailChangeDto: BodyType, + options?: SecondParameter +) => { + return customInstance( + { + url: `/api/v1/auth/email/change-confirm`, + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + data: authConfirmEmailChangeDto, + }, + options + ) +} + +export const getAuthControllerConfirmEmailChangeMutationOptions = < + TError = ErrorType, + TContext = unknown +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { data: BodyType }, + TContext + > + request?: SecondParameter +}): UseMutationOptions< + Awaited>, + TError, + { data: BodyType }, + TContext +> => { + const { mutation: mutationOptions, request: requestOptions } = options ?? {} + + const mutationFn: MutationFunction< + Awaited>, + { data: BodyType } + > = (props) => { + const { data } = props ?? {} + + return authControllerConfirmEmailChange(data, requestOptions) + } + + return { mutationFn, ...mutationOptions } +} + +export type AuthControllerConfirmEmailChangeMutationResult = NonNullable< + Awaited> +> +export type AuthControllerConfirmEmailChangeMutationBody = BodyType +export type AuthControllerConfirmEmailChangeMutationError = ErrorType< + ErrorEntity | ErrorTooManyRequestsEntity | ErrorServerEntity +> + +/** + * @summary Confirm Email Change + */ +export const useAuthControllerConfirmEmailChange = < + TError = ErrorType, + TContext = unknown +>(options?: { + mutation?: UseMutationOptions< + Awaited>, + TError, + { data: BodyType }, + TContext + > + request?: SecondParameter +}) => { + const mutationOptions = getAuthControllerConfirmEmailChangeMutationOptions(options) + + return useMutation(mutationOptions) +} /** * Retrieves information about the current authenticated user * @summary Get Current User diff --git a/src/api/query/users/users.ts b/src/api/query/users/users.ts index ddcbfbb2..952dc8e7 100644 --- a/src/api/query/users/users.ts +++ b/src/api/query/users/users.ts @@ -23,6 +23,7 @@ import type { ErrorEntity, ErrorServerEntity, ErrorUnauthorizedEntity, + ErrorValidationEntity, UpdateUserDto, UserEntity, UsersControllerFindAllParams, @@ -50,7 +51,9 @@ export const usersControllerCreate = ( } export const getUsersControllerCreateMutationOptions = < - TError = ErrorType, + TError = ErrorType< + ErrorUnauthorizedEntity | ErrorEntity | ErrorValidationEntity | ErrorServerEntity + >, TContext = unknown >(options?: { mutation?: UseMutationOptions< @@ -85,14 +88,16 @@ export type UsersControllerCreateMutationResult = NonNullable< > export type UsersControllerCreateMutationBody = BodyType export type UsersControllerCreateMutationError = ErrorType< - ErrorUnauthorizedEntity | ErrorEntity | ErrorServerEntity + ErrorUnauthorizedEntity | ErrorEntity | ErrorValidationEntity | ErrorServerEntity > /** * @summary Create User */ export const useUsersControllerCreate = < - TError = ErrorType, + TError = ErrorType< + ErrorUnauthorizedEntity | ErrorEntity | ErrorValidationEntity | ErrorServerEntity + >, TContext = unknown >(options?: { mutation?: UseMutationOptions< diff --git a/src/api/types/authConfirmEmailChangeDto.ts b/src/api/types/authConfirmEmailChangeDto.ts new file mode 100644 index 00000000..fbae8aee --- /dev/null +++ b/src/api/types/authConfirmEmailChangeDto.ts @@ -0,0 +1,13 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * Generated by orval 🍺 + * Do not edit manually. + * API + * API documentation for the starter-kit project in NestJS by BinarApps. The API allows management of users, sessions and offers various functions for logged in users. Contains examples of authentication, authorization, and CRUD for selected resources. + * OpenAPI spec version: 1.0 + */ + +export interface AuthConfirmEmailChangeDto { + /** The confirmation hash received in the email. */ + hash: string +} diff --git a/src/api/types/authEmailChangeDto.ts b/src/api/types/authEmailChangeDto.ts new file mode 100644 index 00000000..d1901a30 --- /dev/null +++ b/src/api/types/authEmailChangeDto.ts @@ -0,0 +1,13 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * Generated by orval 🍺 + * Do not edit manually. + * API + * API documentation for the starter-kit project in NestJS by BinarApps. The API allows management of users, sessions and offers various functions for logged in users. Contains examples of authentication, authorization, and CRUD for selected resources. + * OpenAPI spec version: 1.0 + */ + +export interface AuthEmailChangeDto { + /** The email address associated with the user account. */ + email: string +} diff --git a/src/api/types/authUpdateDto.ts b/src/api/types/authUpdateDto.ts index ab853aef..1d6365ee 100644 --- a/src/api/types/authUpdateDto.ts +++ b/src/api/types/authUpdateDto.ts @@ -9,13 +9,13 @@ export interface AuthUpdateDto { /** The first name of the user. */ - firstName: string + firstName?: string /** The last name of the user. */ - lastName: string + lastName?: string /** IETF language tags (e.g., en-US). */ - locale: string + locale?: string /** The old password required for security verification when updating user credentials. */ - oldPassword: string + oldPassword?: string /** The new password for updating user credentials. */ - password: string + password?: string } diff --git a/src/api/types/errorValidationEntity.ts b/src/api/types/errorValidationEntity.ts new file mode 100644 index 00000000..38e77c14 --- /dev/null +++ b/src/api/types/errorValidationEntity.ts @@ -0,0 +1,16 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * Generated by orval 🍺 + * Do not edit manually. + * API + * API documentation for the starter-kit project in NestJS by BinarApps. The API allows management of users, sessions and offers various functions for logged in users. Contains examples of authentication, authorization, and CRUD for selected resources. + * OpenAPI spec version: 1.0 + */ +import type { ErrorValidationEntityErrors } from './errorValidationEntityErrors' + +export interface ErrorValidationEntity { + /** Object containing field-specific validation errors */ + errors: ErrorValidationEntityErrors + /** HTTP status code indicating the error */ + status: number +} diff --git a/src/api/types/errorValidationEntityErrors.ts b/src/api/types/errorValidationEntityErrors.ts new file mode 100644 index 00000000..a8893e41 --- /dev/null +++ b/src/api/types/errorValidationEntityErrors.ts @@ -0,0 +1,13 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * Generated by orval 🍺 + * Do not edit manually. + * API + * API documentation for the starter-kit project in NestJS by BinarApps. The API allows management of users, sessions and offers various functions for logged in users. Contains examples of authentication, authorization, and CRUD for selected resources. + * OpenAPI spec version: 1.0 + */ + +/** + * Object containing field-specific validation errors + */ +export type ErrorValidationEntityErrors = { [key: string]: string } diff --git a/src/api/types/index.ts b/src/api/types/index.ts index 3ac56100..cf69b96d 100644 --- a/src/api/types/index.ts +++ b/src/api/types/index.ts @@ -11,7 +11,9 @@ export * from './articleEntity' export * from './articlesControllerFindAllParams' export * from './articlesControllerFindDraftsParams' export * from './authAppleLoginDto' +export * from './authConfirmEmailChangeDto' export * from './authConfirmEmailDto' +export * from './authEmailChangeDto' export * from './authEmailLoginDto' export * from './authEntity' export * from './authFacebookLoginDto' @@ -28,6 +30,8 @@ export * from './errorEntity' export * from './errorServerEntity' export * from './errorTooManyRequestsEntity' export * from './errorUnauthorizedEntity' +export * from './errorValidationEntity' +export * from './errorValidationEntityErrors' export * from './fileEntity' export * from './filesControllerUploadFileBody' export * from './healthCheckInfoDto' diff --git a/src/api/types/lastConsentProperties.ts b/src/api/types/lastConsentProperties.ts index 76306499..25675c10 100644 --- a/src/api/types/lastConsentProperties.ts +++ b/src/api/types/lastConsentProperties.ts @@ -8,6 +8,7 @@ */ export interface LastConsentProperties { + /** The date and time when the consents were last created or the user agreed to the terms for the first time. */ createdAt: string /** Whether the privacy policy was accepted. */ privacyPolicyAccepted: boolean @@ -17,5 +18,6 @@ export interface LastConsentProperties { termsAccepted: boolean /** Version of terms. */ termsVersion: string + /** The date and time of the last update to the consents, indicating when the user last modified their agreement or the consents were refreshed. */ updatedAt: string } diff --git a/src/api/types/updateUserDto.ts b/src/api/types/updateUserDto.ts index d12ce855..af6e7cf2 100644 --- a/src/api/types/updateUserDto.ts +++ b/src/api/types/updateUserDto.ts @@ -14,8 +14,6 @@ export interface UpdateUserDto { email?: string /** The updated first name of the user. */ firstName?: string - /** The updated hash associated with the user account. */ - hash: string /** The updated last name of the user. */ lastName?: string /** IETF language tags (e.g., en-US). */ diff --git a/src/hooks/forms/index.ts b/src/hooks/forms/index.ts index 14f4e5d7..c026210d 100644 --- a/src/hooks/forms/index.ts +++ b/src/hooks/forms/index.ts @@ -1,3 +1,4 @@ export * from './useSignInForm' export * from './useSignUpForm' export * from './useTestForm' +export * from './useUpdateProfileForm' diff --git a/src/hooks/forms/useUpdateProfileForm.ts b/src/hooks/forms/useUpdateProfileForm.ts new file mode 100644 index 00000000..c0e74e6b --- /dev/null +++ b/src/hooks/forms/useUpdateProfileForm.ts @@ -0,0 +1,61 @@ +import { useAuthControllerUpdate, useAuthControllerMe } from '@baca/api/query/auth/auth' +import { AuthUpdateDto } from '@baca/api/types' +// import { AuthUpdateDto } from '@baca/types/profileForm' +import { hapticImpact } from '@baca/utils' +import { handleFormError } from '@baca/utils/handleFormErrors' +import { useMemo, useEffect } from 'react' +import { useForm } from 'react-hook-form' + +export const useUpdateProfileForm = () => { + const { data: userData } = useAuthControllerMe() + const { mutate: userUpdate, isLoading: isSubmitting } = useAuthControllerUpdate() + + const defaultValues: AuthUpdateDto = useMemo( + () => ({ + email: userData?.email || '', + firstName: userData?.firstName || '', + lastName: userData?.lastName || '', + }), + [userData] + ) + + const { + control, + formState: { errors }, + setFocus, + reset, + handleSubmit, + setError: setFormError, + } = useForm({ + mode: 'onTouched', + defaultValues, + }) + + useEffect(() => reset(defaultValues), [reset, defaultValues]) + + const onSubmit = async (data: AuthUpdateDto) => { + userUpdate( + { data }, + { + onError: (e) => { + handleFormError( + e as unknown as keyof AuthUpdateDto, + ({ field, description }) => { + setFormError(field as keyof AuthUpdateDto, { message: description }) + } + ) + + hapticImpact() + }, + } + ) + } + + return { + control, + errors, + isSubmitting, + setFocus, + submit: handleSubmit(onSubmit), + } +} diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json index 8ad79888..c52c0877 100644 --- a/src/i18n/translations/en.json +++ b/src/i18n/translations/en.json @@ -3,11 +3,16 @@ "add": "Add", "back": "Back", "cancel": "Cancel", - "email_label": "E-mail", + "email_label": "Email address", "email_placeholder": "john@doe.com", "empty_list": "The list is empty", + "first_name_placeholder": "John", + "first_name": "First name", "go_back": "Go back", + "last_name_placeholder": "Doe", + "last_name": "Last name", "log_in": "Login", + "password": "Password", "phone_label": "Telephone", "remove": "Remove", "save": "Save", diff --git a/src/screens/ProfileScreen.tsx b/src/screens/ProfileScreen.tsx index 1b858bf2..5c7bd5d4 100644 --- a/src/screens/ProfileScreen.tsx +++ b/src/screens/ProfileScreen.tsx @@ -1,32 +1,148 @@ -import { darkLogo, lightLogo } from '@baca/constants' -import { useColorScheme } from '@baca/contexts' -import { Center, Text } from '@baca/design-system' -import { useScreenOptions } from '@baca/hooks' -import { Image, StyleSheet } from 'react-native' +import { ControlledField } from '@baca/components' +import { Button, Text, Spacer, palette, size } from '@baca/design-system' +import { + useMemo, + useCallback, + useTranslation, + useUpdateProfileForm, + useScreenOptions, +} from '@baca/hooks' +import { useRouter } from 'expo-router' +import { InputModeOptions, StyleSheet, View } from 'react-native' export const ProfileScreen = () => { - useScreenOptions({ - title: 'Profile', - }) + useScreenOptions({ headerShown: false }) - const { colorScheme } = useColorScheme() + const { back } = useRouter() + const { t } = useTranslation() + + const { control, errors, isSubmitting, setFocus, submit } = useUpdateProfileForm() + + const focusLastNameInput = useCallback(() => setFocus('lastName'), [setFocus]) + + const inputs = useMemo( + () => [ + { + inputMode: 'text', + label: t('common.first_name'), + name: 'firstName', + onFocuse: focusLastNameInput, + testID: 'firstNameInput', + placeholder: '', + }, + { + inputMode: 'text', + label: t('common.last_name'), + name: 'lastName', + testID: 'firstNameInput', + placeholder: '', + }, + { + inputMode: 'email', + isDisabled: true, + label: t('common.email_label'), + name: 'email', + testID: 'emailInput', + placeholder: '', + }, + // { + // inputMode: 'password', + // isDisabled: true, + // label: t('common.password'), + // name: 'password', + // testID: 'passwordInput', + // type: 'password', + // }, + ], + [t, focusLastNameInput] + ) + + const renderInputs = useCallback( + () => + inputs.map(({ inputMode, isDisabled, label, name, onFocuse, testID, placeholder }, index) => ( + + + {label} + + + + + )), + [control, errors, inputs] + ) return ( -
- - Profile screen -
+ + Profile + Update your personal details here. + + {renderInputs()} + {/* */} + + + + + + + ) } const styles = StyleSheet.create({ - logo: { - height: 100, + buttonsContainer: { + borderColor: palette.gray[300], + borderTopWidth: size[0.5], + flexDirection: 'row', + justifyContent: 'flex-end', width: '100%', }, + container: { + marginHorizontal: size[8], + marginVertical: size[8], + }, + inputContainer: { + alignItems: 'center', + flex: 1, + flexDirection: 'row', + flexGrow: 1, + marginTop: size[4], + width: '50%', + }, + labelWrapper: { + width: '50%', + }, + sectionContainer: { + borderColor: palette.gray[300], + borderTopWidth: size[0.5], + marginVertical: size[8], + }, }) From 21c1bbf05a35bb102faa768b0926c48fc65f1d1e Mon Sep 17 00:00:00 2001 From: Lukasz Borkowski Date: Sat, 9 Mar 2024 17:52:10 +0100 Subject: [PATCH 02/14] added field types and placeholders --- src/constants/fieldTypes.ts | 6 ++++++ src/constants/index.ts | 1 + src/screens/ProfileScreen.tsx | 16 +++++++++------- 3 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 src/constants/fieldTypes.ts diff --git a/src/constants/fieldTypes.ts b/src/constants/fieldTypes.ts new file mode 100644 index 00000000..23e18e0e --- /dev/null +++ b/src/constants/fieldTypes.ts @@ -0,0 +1,6 @@ +export enum FieldTypes { + //ProfileScreen + FIRST_NAME = 'firstName', + LAST_NAME = 'password', + EMAIL = 'email', +} diff --git a/src/constants/index.ts b/src/constants/index.ts index fcbb97bd..69396eef 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -2,6 +2,7 @@ export * from './asyncStorageKeys' export * from './colorSchemes' export * from './env' export * from './environments' +export * from './fieldTypes' export * from './images' export * from './navigation' export * from './regex' diff --git a/src/screens/ProfileScreen.tsx b/src/screens/ProfileScreen.tsx index 5c7bd5d4..3785f04b 100644 --- a/src/screens/ProfileScreen.tsx +++ b/src/screens/ProfileScreen.tsx @@ -1,4 +1,5 @@ import { ControlledField } from '@baca/components' +import { FieldTypes } from '@baca/constants' import { Button, Text, Spacer, palette, size } from '@baca/design-system' import { useMemo, @@ -10,6 +11,8 @@ import { import { useRouter } from 'expo-router' import { InputModeOptions, StyleSheet, View } from 'react-native' +const { FIRST_NAME, LAST_NAME, EMAIL } = FieldTypes + export const ProfileScreen = () => { useScreenOptions({ headerShown: false }) @@ -25,25 +28,25 @@ export const ProfileScreen = () => { { inputMode: 'text', label: t('common.first_name'), - name: 'firstName', + name: FIRST_NAME, onFocuse: focusLastNameInput, testID: 'firstNameInput', - placeholder: '', + placeholder: t('common.first_name_placeholder'), }, { inputMode: 'text', label: t('common.last_name'), - name: 'lastName', + name: LAST_NAME, testID: 'firstNameInput', - placeholder: '', + placeholder: t('common.last_name_placeholder'), }, { inputMode: 'email', isDisabled: true, label: t('common.email_label'), - name: 'email', + name: EMAIL, testID: 'emailInput', - placeholder: '', + placeholder: t('common.email_placeholder'), }, // { // inputMode: 'password', @@ -74,7 +77,6 @@ export const ProfileScreen = () => { testID={testID} isDisabled={isDisabled} placeholder={placeholder} - // rules={} /> )), From 16339cc6a8ff141acc39c890726edb2088d3322d Mon Sep 17 00:00:00 2001 From: Lukasz Borkowski Date: Sat, 9 Mar 2024 23:58:35 +0100 Subject: [PATCH 03/14] translations and test labels fix --- src/constants/fieldTypes.ts | 3 ++- src/i18n/translations/en.json | 10 ++++++++++ src/screens/ProfileScreen.tsx | 28 ++++++++++++++-------------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/constants/fieldTypes.ts b/src/constants/fieldTypes.ts index 23e18e0e..ee69bbc9 100644 --- a/src/constants/fieldTypes.ts +++ b/src/constants/fieldTypes.ts @@ -1,6 +1,7 @@ export enum FieldTypes { //ProfileScreen FIRST_NAME = 'firstName', - LAST_NAME = 'password', + LAST_NAME = 'lastName', EMAIL = 'email', + PASSWORD = 'password', } diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json index c52c0877..3ace36f7 100644 --- a/src/i18n/translations/en.json +++ b/src/i18n/translations/en.json @@ -81,6 +81,16 @@ "application_info_screen": { "navigation_info": "When you will try to go back it will double ask if you really want to leave \n" }, + "profile_screen": { + "first_name": "First name", + "first_name_placeholder": "Enter your first name", + "last_name": "Last name", + "last_name_placeholder": "Enter your last name", + "email_label": "Email address", + "email_placeholder": "Enter your email", + "save": "Save", + "cancel": "Cancel" + }, "colors_screen": { "colors_label": "Colors" }, diff --git a/src/screens/ProfileScreen.tsx b/src/screens/ProfileScreen.tsx index 3785f04b..6536bf75 100644 --- a/src/screens/ProfileScreen.tsx +++ b/src/screens/ProfileScreen.tsx @@ -27,33 +27,33 @@ export const ProfileScreen = () => { () => [ { inputMode: 'text', - label: t('common.first_name'), + label: t('profile_screen.first_name'), name: FIRST_NAME, onFocuse: focusLastNameInput, - testID: 'firstNameInput', - placeholder: t('common.first_name_placeholder'), + testID: `${FIRST_NAME}Input`, + placeholder: t('profile_screen.first_name_placeholder'), }, { inputMode: 'text', - label: t('common.last_name'), + label: t('profile_screen.last_name'), name: LAST_NAME, - testID: 'firstNameInput', - placeholder: t('common.last_name_placeholder'), + testID: `${LAST_NAME}Input`, + placeholder: t('profile_screen.last_name_placeholder'), }, { inputMode: 'email', isDisabled: true, - label: t('common.email_label'), + label: t('profile_screen.email_label'), name: EMAIL, - testID: 'emailInput', - placeholder: t('common.email_placeholder'), + testID: `${EMAIL}Input`, + placeholder: t('profile_screen.email_placeholder'), }, // { // inputMode: 'password', // isDisabled: true, - // label: t('common.password'), - // name: 'password', - // testID: 'passwordInput', + // label: t('profile_screen.password'), + // name: PASSWORD, + // testID: `${PASSWORD}Input`, // type: 'password', // }, ], @@ -102,7 +102,7 @@ export const ProfileScreen = () => { borderWidth={1} testID="backProfileButton" > - {t('common.cancel')} + {t('profile_screen.cancel')} From 60518d30af06b92b337ba415aa3e29f73a81ba26 Mon Sep 17 00:00:00 2001 From: Lukasz Borkowski Date: Sun, 10 Mar 2024 00:46:13 +0100 Subject: [PATCH 04/14] added types --- src/constants/fieldTypes.ts | 11 +++++++++++ src/screens/ProfileScreen.tsx | 5 ++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/constants/fieldTypes.ts b/src/constants/fieldTypes.ts index ee69bbc9..4750b2db 100644 --- a/src/constants/fieldTypes.ts +++ b/src/constants/fieldTypes.ts @@ -5,3 +5,14 @@ export enum FieldTypes { EMAIL = 'email', PASSWORD = 'password', } + +export type Input = { + inputMode: string + isDisabled?: boolean + label: string + name: FieldTypes + onFocuse?: () => void + placeholder: string + testID: string + type?: string +} diff --git a/src/screens/ProfileScreen.tsx b/src/screens/ProfileScreen.tsx index 6536bf75..69f0f779 100644 --- a/src/screens/ProfileScreen.tsx +++ b/src/screens/ProfileScreen.tsx @@ -1,5 +1,5 @@ import { ControlledField } from '@baca/components' -import { FieldTypes } from '@baca/constants' +import { FieldTypes, Input } from '@baca/constants' import { Button, Text, Spacer, palette, size } from '@baca/design-system' import { useMemo, @@ -23,7 +23,7 @@ export const ProfileScreen = () => { const focusLastNameInput = useCallback(() => setFocus('lastName'), [setFocus]) - const inputs = useMemo( + const inputs: Input[] = useMemo( () => [ { inputMode: 'text', @@ -89,7 +89,6 @@ export const ProfileScreen = () => { Update your personal details here. {renderInputs()} - {/* */} From 7713ba65d4e1a0e53113a496697d8fb62035de23 Mon Sep 17 00:00:00 2001 From: Mateusz Rostkowski Date: Mon, 11 Mar 2024 20:06:25 +0100 Subject: [PATCH 06/14] chore: unify sign in form --- src/hooks/forms/useSignInForm.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/hooks/forms/useSignInForm.ts b/src/hooks/forms/useSignInForm.ts index 55e75b6d..f7cc8816 100644 --- a/src/hooks/forms/useSignInForm.ts +++ b/src/hooks/forms/useSignInForm.ts @@ -1,11 +1,15 @@ import { useAuthControllerLogin } from '@baca/api/query/auth/auth' +import { AuthEmailLoginDto } from '@baca/api/types' import { setToken } from '@baca/services' import { isSignedInAtom } from '@baca/store/auth' -import { SignInFormValues } from '@baca/types/authForms' import { hapticImpact } from '@baca/utils' +import { handleFormError } from '@baca/utils/handleFormErrors' import { useSetAtom } from 'jotai' import { useForm } from 'react-hook-form' -import { notify } from 'react-native-notificated' + +type SignInFormValues = AuthEmailLoginDto & { + confirm: boolean +} const defaultValues: SignInFormValues = { // TODO: Reset this values when building production app @@ -24,8 +28,9 @@ export const useSignInForm = () => { const { control, formState: { errors }, - setFocus, handleSubmit, + setError: setFormError, + setFocus, } = useForm({ mode: 'onTouched', defaultValues, @@ -40,7 +45,13 @@ export const useSignInForm = () => { // FIXME: add proper notification handling, generate some global config { onError: (e) => { - notify('error', { params: { title: 'ERROR', description: e?.message } }) + handleFormError( + e as unknown as keyof AuthEmailLoginDto, + ({ field, description }) => { + setFormError(field as keyof AuthEmailLoginDto, { message: description }) + } + ) + hapticImpact() }, onSuccess: async (response) => { From 00867d7618dd64b160f6d4bc2df3dd5e67053924 Mon Sep 17 00:00:00 2001 From: Mateusz Rostkowski Date: Mon, 11 Mar 2024 20:08:48 +0100 Subject: [PATCH 07/14] chore: unify user profile form --- src/hooks/forms/useUpdateProfileForm.ts | 27 ++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/hooks/forms/useUpdateProfileForm.ts b/src/hooks/forms/useUpdateProfileForm.ts index c0e74e6b..6c9581ad 100644 --- a/src/hooks/forms/useUpdateProfileForm.ts +++ b/src/hooks/forms/useUpdateProfileForm.ts @@ -1,14 +1,16 @@ import { useAuthControllerUpdate, useAuthControllerMe } from '@baca/api/query/auth/auth' import { AuthUpdateDto } from '@baca/api/types' -// import { AuthUpdateDto } from '@baca/types/profileForm' import { hapticImpact } from '@baca/utils' import { handleFormError } from '@baca/utils/handleFormErrors' import { useMemo, useEffect } from 'react' import { useForm } from 'react-hook-form' +import { useTranslation } from 'react-i18next' +import { notify } from 'react-native-notificated' export const useUpdateProfileForm = () => { const { data: userData } = useAuthControllerMe() - const { mutate: userUpdate, isLoading: isSubmitting } = useAuthControllerUpdate() + const { t } = useTranslation() + const { mutate: updateUserMutation, isLoading } = useAuthControllerUpdate() const defaultValues: AuthUpdateDto = useMemo( () => ({ @@ -22,21 +24,32 @@ export const useUpdateProfileForm = () => { const { control, formState: { errors }, - setFocus, - reset, handleSubmit, + reset, setError: setFormError, + setFocus, } = useForm({ mode: 'onTouched', defaultValues, }) - useEffect(() => reset(defaultValues), [reset, defaultValues]) + useEffect(() => { + reset(defaultValues) + }, [reset, defaultValues]) const onSubmit = async (data: AuthUpdateDto) => { - userUpdate( + await updateUserMutation( { data }, { + onSuccess: () => { + notify('success', { + params: { + style: { multiline: 100 }, + title: 'SUCCESS', + description: t('profile_screen.update_profile_success'), + }, + }) + }, onError: (e) => { handleFormError( e as unknown as keyof AuthUpdateDto, @@ -54,7 +67,7 @@ export const useUpdateProfileForm = () => { return { control, errors, - isSubmitting, + isSubmitting: isLoading, setFocus, submit: handleSubmit(onSubmit), } From 3919c660e64ed586fbdc2129bf7a6ab58962f0ed Mon Sep 17 00:00:00 2001 From: Mateusz Rostkowski Date: Mon, 11 Mar 2024 20:13:04 +0100 Subject: [PATCH 08/14] chore: update translations --- src/i18n/translations/en.json | 3 ++- src/i18n/translations/pl.json | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json index 00d0ab6a..64216a7c 100644 --- a/src/i18n/translations/en.json +++ b/src/i18n/translations/en.json @@ -90,7 +90,8 @@ "email_label": "Email address", "email_placeholder": "Enter your email", "save": "Save", - "cancel": "Cancel" + "cancel": "Cancel", + "update_profile_success": "Poprawnie zaktualizowano dane osobowe." }, "colors_screen": { "colors_label": "Colors" diff --git a/src/i18n/translations/pl.json b/src/i18n/translations/pl.json index da2299af..9ee0f258 100644 --- a/src/i18n/translations/pl.json +++ b/src/i18n/translations/pl.json @@ -77,6 +77,17 @@ "application_info_screen": { "navigation_info": "Kiedy będziesz próbował cofnąć to zostaniesz podwójnie zapytany, czy na pewno tego chcesz \n" }, + "profile_screen": { + "first_name": "Imię", + "first_name_placeholder": "Podaj swoje imię", + "last_name": "Nazwisko", + "last_name_placeholder": "Podaj swoje nazwisko", + "email_label": "Adres mailowy", + "email_placeholder": "Podaj swój e-mail", + "save": "Zapisz", + "cancel": "Anuluj", + "update_profile_success": "Poprawnie zaktualizowano Twoje dane." + }, "colors_screen": { "colors_label": "Kolory" }, From 3276e0b904acaf3264c571fd7df1b2242dccb303 Mon Sep 17 00:00:00 2001 From: Mateusz Rostkowski Date: Mon, 11 Mar 2024 20:13:19 +0100 Subject: [PATCH 09/14] chore: remove not needed types file --- src/types/authForms.ts | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 src/types/authForms.ts diff --git a/src/types/authForms.ts b/src/types/authForms.ts deleted file mode 100644 index af0838de..00000000 --- a/src/types/authForms.ts +++ /dev/null @@ -1,13 +0,0 @@ -export type SignUpFormValues = { - user: string - email: string - password: string - agree: boolean - newsletter: boolean -} - -export type SignInFormValues = { - email: string - password: string - confirm: boolean -} From 15361dd5e37d6d7daf22aa98574e7c3d040330c4 Mon Sep 17 00:00:00 2001 From: Mateusz Rostkowski Date: Mon, 11 Mar 2024 20:13:36 +0100 Subject: [PATCH 10/14] chore: add vercel to gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c49f35d8..87431789 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,6 @@ GoogleService-Info.plist scripts/doppler_variables.sh .env -env.json \ No newline at end of file +env.json + +.vercel \ No newline at end of file From e1e9c45281d291dbdc992156faea66b9eed20776 Mon Sep 17 00:00:00 2001 From: Mateusz Rostkowski Date: Mon, 11 Mar 2024 20:14:10 +0100 Subject: [PATCH 11/14] chore: update translations --- src/i18n/translations/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json index 64216a7c..90f9b0e2 100644 --- a/src/i18n/translations/en.json +++ b/src/i18n/translations/en.json @@ -91,7 +91,7 @@ "email_placeholder": "Enter your email", "save": "Save", "cancel": "Cancel", - "update_profile_success": "Poprawnie zaktualizowano dane osobowe." + "update_profile_success": "Successfuly updated your data." }, "colors_screen": { "colors_label": "Colors" From f4505a1fddaf7841554bae230e141486dedb183d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Baumruck?= Date: Thu, 14 Mar 2024 10:01:34 +0100 Subject: [PATCH 12/14] add some refactor, clean up translations files --- src/constants/fieldTypes.ts | 18 --- src/constants/index.ts | 1 - src/hooks/forms/useSignInForm.ts | 2 +- src/hooks/forms/useSignUpForm.ts | 8 +- src/hooks/forms/useUpdateProfileForm.ts | 6 +- src/i18n/translations/en.json | 129 +++++++++---------- src/i18n/translations/pl.json | 90 ++++++------- src/screens/ProfileScreen.tsx | 162 +++++++----------------- src/screens/SignInScreen.tsx | 14 +- src/screens/SignUpScreen.tsx | 28 ++-- src/utils/getApiError.ts | 4 +- 11 files changed, 173 insertions(+), 289 deletions(-) delete mode 100644 src/constants/fieldTypes.ts diff --git a/src/constants/fieldTypes.ts b/src/constants/fieldTypes.ts deleted file mode 100644 index 4750b2db..00000000 --- a/src/constants/fieldTypes.ts +++ /dev/null @@ -1,18 +0,0 @@ -export enum FieldTypes { - //ProfileScreen - FIRST_NAME = 'firstName', - LAST_NAME = 'lastName', - EMAIL = 'email', - PASSWORD = 'password', -} - -export type Input = { - inputMode: string - isDisabled?: boolean - label: string - name: FieldTypes - onFocuse?: () => void - placeholder: string - testID: string - type?: string -} diff --git a/src/constants/index.ts b/src/constants/index.ts index 69396eef..fcbb97bd 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -2,7 +2,6 @@ export * from './asyncStorageKeys' export * from './colorSchemes' export * from './env' export * from './environments' -export * from './fieldTypes' export * from './images' export * from './navigation' export * from './regex' diff --git a/src/hooks/forms/useSignInForm.ts b/src/hooks/forms/useSignInForm.ts index f7cc8816..beb116da 100644 --- a/src/hooks/forms/useSignInForm.ts +++ b/src/hooks/forms/useSignInForm.ts @@ -48,7 +48,7 @@ export const useSignInForm = () => { handleFormError( e as unknown as keyof AuthEmailLoginDto, ({ field, description }) => { - setFormError(field as keyof AuthEmailLoginDto, { message: description }) + setFormError(field, { message: description }) } ) diff --git a/src/hooks/forms/useSignUpForm.ts b/src/hooks/forms/useSignUpForm.ts index 268eacb9..6640d1e3 100644 --- a/src/hooks/forms/useSignUpForm.ts +++ b/src/hooks/forms/useSignUpForm.ts @@ -18,7 +18,7 @@ const defaultValues: AuthRegisterLoginDto = { } export const useSignUpForm = () => { - const { mutateAsync: loginMutation, isLoading } = useAuthControllerRegister() + const { mutate: loginMutation, isLoading } = useAuthControllerRegister() const { t } = useTranslation() const { @@ -32,8 +32,8 @@ export const useSignUpForm = () => { defaultValues, }) - const onSubmit = async (data: AuthRegisterLoginDto) => { - await loginMutation( + const onSubmit = (data: AuthRegisterLoginDto) => { + loginMutation( { data, }, @@ -51,7 +51,7 @@ export const useSignUpForm = () => { handleFormError( e as unknown as keyof AuthRegisterLoginDto, ({ field, description }) => { - setFormError(field as keyof AuthRegisterLoginDto, { message: description }) + setFormError(field, { message: description }) } ) hapticImpact() diff --git a/src/hooks/forms/useUpdateProfileForm.ts b/src/hooks/forms/useUpdateProfileForm.ts index 6c9581ad..1751a63c 100644 --- a/src/hooks/forms/useUpdateProfileForm.ts +++ b/src/hooks/forms/useUpdateProfileForm.ts @@ -37,8 +37,8 @@ export const useUpdateProfileForm = () => { reset(defaultValues) }, [reset, defaultValues]) - const onSubmit = async (data: AuthUpdateDto) => { - await updateUserMutation( + const onSubmit = (data: AuthUpdateDto) => { + updateUserMutation( { data }, { onSuccess: () => { @@ -54,7 +54,7 @@ export const useUpdateProfileForm = () => { handleFormError( e as unknown as keyof AuthUpdateDto, ({ field, description }) => { - setFormError(field as keyof AuthUpdateDto, { message: description }) + setFormError(field, { message: description }) } ) diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json index 90f9b0e2..62c3fc29 100644 --- a/src/i18n/translations/en.json +++ b/src/i18n/translations/en.json @@ -3,50 +3,55 @@ "add": "Add", "back": "Back", "cancel": "Cancel", - "email_label": "Email address", - "email_placeholder": "john@doe.com", - "empty_list": "The list is empty", - "first_name_placeholder": "John", - "first_name": "First name", "go_back": "Go back", - "last_name_placeholder": "Doe", - "last_name": "Last name", - "log_in": "Login", - "password": "Password", - "phone_label": "Telephone", "remove": "Remove", "save": "Save", "search": "Search", - "send_again": "Send again", - "show_on_map": "Show on map", - "sign_in": "Sign in", - "sign_up": "Register", "try_again_later": "Please try again later", - "try_again": "Try again", - "user_label": "User", - "user_placeholder": "user" + "try_again": "Try again" }, "errors": { + "invalid_email": "Niepoprawny adres e-mail", + "invalid_password": "Niepoprawne hasło", + "missing_auth": "Missing auth", "screen_not_found": "NotFound screen", "something_went_wrong": "Something went wrong", - "token_expired": "Token expired", - "missing_auth": "Missing auth" + "token_expired": "Token expired" + }, + "examples_component": { + "example": "Example" }, "form": { - "invalid_email_format": "Incorrect e-mail address", - "invalid_password_format": "Password must be at least 8 characters long, contain at least one uppercase letter, one lowercase letter, one number, and one special character", - "invalid_password": "Incorrect password", - "required": "This field is required" + "errors": {}, + "labels": { + "email": "E-mail address", + "first_name": "First name", + "last_name": "Last name", + "password": "Password" + }, + "placeholders": { + "create_password": "Create a password", + "email": "Enter your email", + "first_name": "Enter your first name", + "last_name": "Enter your last name", + "password": "Password" + }, + "validation": { + "invalid_email_format": "Incorrect e-mail address format", + "invalid_password_format": "Password must be at least 8 characters long, contain at least one uppercase letter, one lowercase letter, one number, and one special character", + "required": "This field is required" + } }, "navigation": { "prevent_go_back_alert": { - "title": "Discard changes?", "description": "You have unsaved changes. Are you sure to discard them and leave the screen?", + "discard": "Discard", "do_not_leave": "Don't leave", - "discard": "Discard" + "title": "Discard changes?" }, "screen_titles": { "application_info": "ApplicationInfo", + "blog": "Blog", "colors": "Colors", "components": "Components", "data_from_be_screen_example": "Data from BE", @@ -60,55 +65,23 @@ "settings": "Settings", "sign_in": "Sign in", "sign_up": "Sign up", - "typography": "Typography", "test_form": "Test form", - "blog": "Blog" + "typography": "Typography" } }, "update": { - "alert_title": "New version available", "alert_message": "You will have to restart the application to have better experiences while using it", + "alert_title": "New version available", "restart": "Restart" }, - "examples_component": { - "example": "Example" - }, - "landing_screen": { - "go_to_blog": "Open blog", - "go_to_form": "Open full screen form", - "login_cta": "Log in", - "sign_up": "Sign up" - }, + "application_info_screen": { "navigation_info": "When you will try to go back it will double ask if you really want to leave \n" }, - "profile_screen": { - "first_name": "First name", - "first_name_placeholder": "Enter your first name", - "last_name": "Last name", - "last_name_placeholder": "Enter your last name", - "email_label": "Email address", - "email_placeholder": "Enter your email", - "save": "Save", - "cancel": "Cancel", - "update_profile_success": "Successfuly updated your data." - }, "colors_screen": { "colors_label": "Colors" }, "components_screen": { - "test_notification": "Test notification", - "typography": { - "label": "Typography", - "xs": "xs", - "sm": "sm", - "md": "md", - "lg": "lg", - "xl": "xl", - "2xl": "2xl", - "3xl": "3xl", - "4xl": "4xl" - }, "button_variants": { "disabled": "Button disabled", "ghost": "Button ghost", @@ -120,6 +93,7 @@ "secondary": "Button secondary", "with_icons": "Button with icons" }, + "loader_variants": { "bricks": "Bricks loader", "bubbles": "Bubbles loader", @@ -131,6 +105,18 @@ "notification": { "description": "by react-native-notificated 🎉", "title": "In-app notification example" + }, + "test_notification": "Test notification", + "typography": { + "label": "Typography", + "xs": "xs", + "sm": "sm", + "md": "md", + "lg": "lg", + "xl": "xl", + "2xl": "2xl", + "3xl": "3xl", + "4xl": "4xl" } }, "details_screen": { @@ -153,6 +139,15 @@ "home_screen": { "details": "Details" }, + "landing_screen": { + "go_to_blog": "Open blog", + "go_to_form": "Open full screen form", + "login_cta": "Log in", + "sign_up": "Sign up" + }, + "profile_screen": { + "update_profile_success": "Successfully updated your data." + }, "settings_screen": { "copy_push_token": "Copy push token", "current_theme": "Current theme: {{theme}}", @@ -165,27 +160,17 @@ "forgot_password": "Forgot your password?", "or_pass": "or enter:", "password_helper_text": "Password must be here", - "password_label": "Password", - "password_placeholder": "password", "remember_me": "Remember me", "sign_in": "Sign in", "sign_up": "Sign up" }, "sign_up_screen": { "created_new_account": "A new account has been created. An email with an activation link was sent to {{userEmail}}.", - "email_label": "Email", - "email_placeholder": "Enter your email", - "first_name_label": "First name", - "first_name_placeholder": "Enter your first name", - "last_name_label": "Last name", - "last_name_placeholder": "Enter your last name", "newsletter_label": "Subscribe to our newsletter", - "password_placeholder": "Create a password", - "password_label": "Password", "privacy_policy_label": "I’ve read and accept Privacy Policy", "sign_up": "Sign up", - "trail_descirption": "Start your 30-day free trial.", - "terms_accepted_label": "I agree to the Terms and Conditions" + "terms_accepted_label": "I agree to the Terms and Conditions", + "trail_description": "Start your 30-day free trial." }, "test_form": { "additional_comment": "Additional comment", diff --git a/src/i18n/translations/pl.json b/src/i18n/translations/pl.json index 9ee0f258..7b0aa781 100644 --- a/src/i18n/translations/pl.json +++ b/src/i18n/translations/pl.json @@ -3,35 +3,44 @@ "add": "Dodaj", "back": "Cofnij", "cancel": "Anuluj", - "email_label": "E-mail", - "email_placeholder": "john@doe.com", - "empty_list": "Lista jest pusta", "go_back": "Cofnij", - "log_in": "Login", - "phone_label": "Telefon", "remove": "Usuń", "save": "Zapisz", "search": "Szukaj", - "send_again": "Wyślij ponownie", - "show_on_map": "Pokaż na mapie", - "sign_in": "Zaloguj", - "sign_up": "Zarejestruj", "try_again_later": "Proszę spróbuj ponownie później", - "try_again": "Spróbuj ponownie", - "user_label": "Użytkownik", - "user_placeholder": "Użytkownik" + "try_again": "Spróbuj ponownie" }, "errors": { + "invalid_email": "Niepoprawny adres e-mail", + "invalid_password": "Niepoprawne hasło", "missing_auth": "Brak autoryzacji", "screen_not_found": "NotFound screen", "something_went_wrong": "Coś poszło nie tak", "token_expired": "Token wygasł" }, + "examples_component": { + "example": "Przykład" + }, "form": { - "invalid_email_format": "Zły adres e-mail", - "invalid_password_format": "Hasło musi zawierać minimum: 8 znaków, jedną wielką literę, jedną malą literę, jedną cyfrę i jeden znak specjalny", - "invalid_password": "Niepoprawne hasło", - "required": "Pole wymagane" + "errors": {}, + "labels": { + "email": "Adres e-mail", + "first_name": "Imię", + "last_name": "Nazwisko", + "password": "Hasło" + }, + "placeholders": { + "create_password": "Utwórz nowe hasło", + "email": "Podaj adres e-mail", + "first_name": "Podaj swoje imię", + "last_name": "Podaj swoje nazwisko", + "password": "Hasło" + }, + "validation": { + "invalid_email_format": "Niepoprawny format adresu e-mail", + "invalid_password_format": "Hasło musi zawierać minimum: 8 znaków, jedną wielką literę, jedną małą literę, jedną cyfrę i jeden znak specjalny", + "required": "Pole wymagane" + } }, "navigation": { "prevent_go_back_alert": { @@ -42,6 +51,7 @@ }, "screen_titles": { "application_info": "ApplicationInfo", + "blog": "Blog", "colors": "Colors", "components": "Components", "data_from_be_screen_example": "Dane z backend-u", @@ -55,9 +65,8 @@ "settings": "Settings", "sign_in": "Sign in", "sign_up": "Sign up", - "typography": "Typography", "test_form": "Formularz testowy", - "blog": "Blog" + "typography": "Typography" } }, "update": { @@ -65,29 +74,10 @@ "alert_title": "Aktualizacja", "restart": "Zrestartuj" }, - "examples_component": { - "example": "Przykład" - }, - "landing_screen": { - "login_cta": "Zaloguj się", - "sign_up": "Zarejestruj się", - "go_to_blog": "Otwórz blog", - "go_to_form": "Otwórz pełno ekranowy formularz full" - }, + "application_info_screen": { "navigation_info": "Kiedy będziesz próbował cofnąć to zostaniesz podwójnie zapytany, czy na pewno tego chcesz \n" }, - "profile_screen": { - "first_name": "Imię", - "first_name_placeholder": "Podaj swoje imię", - "last_name": "Nazwisko", - "last_name_placeholder": "Podaj swoje nazwisko", - "email_label": "Adres mailowy", - "email_placeholder": "Podaj swój e-mail", - "save": "Zapisz", - "cancel": "Anuluj", - "update_profile_success": "Poprawnie zaktualizowano Twoje dane." - }, "colors_screen": { "colors_label": "Kolory" }, @@ -148,6 +138,15 @@ "home_screen": { "details": "Detale" }, + "landing_screen": { + "login_cta": "Zaloguj się", + "sign_up": "Zarejestruj się", + "go_to_blog": "Otwórz blog", + "go_to_form": "Otwórz pełno ekranowy formularz full" + }, + "profile_screen": { + "update_profile_success": "Poprawnie zaktualizowano Twoje dane." + }, "settings_screen": { "current_theme": "Current theme: {{theme}}", "selected": " - wybrano", @@ -159,8 +158,6 @@ "forgot_password": "Zapomniałeś hasła?", "or_pass": "lub wprowadź:", "password_helper_text": "Hasła muszą być takie same", - "password_label": "Hasło", - "password_placeholder": "hasło", "remember_me": "Zapamiętaj mnie", "sign_in": "Zaloguj", "sign_up": "Zarejestruj" @@ -168,18 +165,11 @@ "sign_up_screen": { "created_new_account": "Nowe konto zostało stworzone. Email z linkiem weryfikacyjnym został wysłany na {{userEmail}}.", "newsletter_label": "Subskrybuj nasz newsletter", - "sign_up": "Zarejestruj", - "email_label": "E-mail", - "email_placeholder": "Podaj swój e-mail", - "first_name_label": "Imię", - "first_name_placeholder": "Wprowadź imię", - "last_name_label": "Nazwisko", - "last_name_placeholder": "Wprowadź nazwisko", - "password_placeholder": "Nowe hasło", "password_label": "Hasło", "privacy_policy_label": "Zapoznałem się i akceptuję politykę prywatności", - "trail_descirption": "Rozpocznij darmowy 30 dniowy okres próbny.", - "terms_accepted_label": "Zgadzam się z warunkami użytkowania" + "sign_up": "Zarejestruj", + "terms_accepted_label": "Zgadzam się z warunkami użytkowania", + "trail_description": "Rozpocznij darmowy 30 dniowy okres próbny." }, "test_form": { "additional_comment": "Dodatkowy komentarz", diff --git a/src/screens/ProfileScreen.tsx b/src/screens/ProfileScreen.tsx index 69f0f779..d3e9b521 100644 --- a/src/screens/ProfileScreen.tsx +++ b/src/screens/ProfileScreen.tsx @@ -1,108 +1,66 @@ import { ControlledField } from '@baca/components' -import { FieldTypes, Input } from '@baca/constants' -import { Button, Text, Spacer, palette, size } from '@baca/design-system' -import { - useMemo, - useCallback, - useTranslation, - useUpdateProfileForm, - useScreenOptions, -} from '@baca/hooks' +import { Button, Text, Spacer, Row, Box } from '@baca/design-system' +import { useCallback, useTranslation, useUpdateProfileForm, useScreenOptions } from '@baca/hooks' import { useRouter } from 'expo-router' -import { InputModeOptions, StyleSheet, View } from 'react-native' - -const { FIRST_NAME, LAST_NAME, EMAIL } = FieldTypes export const ProfileScreen = () => { - useScreenOptions({ headerShown: false }) - - const { back } = useRouter() const { t } = useTranslation() + const { back } = useRouter() + + useScreenOptions({ headerShown: false }) const { control, errors, isSubmitting, setFocus, submit } = useUpdateProfileForm() const focusLastNameInput = useCallback(() => setFocus('lastName'), [setFocus]) - const inputs: Input[] = useMemo( - () => [ - { - inputMode: 'text', - label: t('profile_screen.first_name'), - name: FIRST_NAME, - onFocuse: focusLastNameInput, - testID: `${FIRST_NAME}Input`, - placeholder: t('profile_screen.first_name_placeholder'), - }, - { - inputMode: 'text', - label: t('profile_screen.last_name'), - name: LAST_NAME, - testID: `${LAST_NAME}Input`, - placeholder: t('profile_screen.last_name_placeholder'), - }, - { - inputMode: 'email', - isDisabled: true, - label: t('profile_screen.email_label'), - name: EMAIL, - testID: `${EMAIL}Input`, - placeholder: t('profile_screen.email_placeholder'), - }, - // { - // inputMode: 'password', - // isDisabled: true, - // label: t('profile_screen.password'), - // name: PASSWORD, - // testID: `${PASSWORD}Input`, - // type: 'password', - // }, - ], - [t, focusLastNameInput] - ) - - const renderInputs = useCallback( - () => - inputs.map(({ inputMode, isDisabled, label, name, onFocuse, testID, placeholder }, index) => ( - - - {label} - - - - - )), - [control, errors, inputs] - ) - return ( - + Profile Update your personal details here. - {renderInputs()} + + + + + - - + {t('common.cancel')} + - - + + ) } - -const styles = StyleSheet.create({ - buttonsContainer: { - borderColor: palette.gray[300], - borderTopWidth: size[0.5], - flexDirection: 'row', - justifyContent: 'flex-end', - width: '100%', - }, - container: { - marginHorizontal: size[8], - marginVertical: size[8], - }, - inputContainer: { - alignItems: 'center', - flex: 1, - flexDirection: 'row', - flexGrow: 1, - marginTop: size[4], - width: '50%', - }, - labelWrapper: { - width: '50%', - }, - sectionContainer: { - borderColor: palette.gray[300], - borderTopWidth: size[0.5], - marginVertical: size[8], - }, -}) diff --git a/src/screens/SignInScreen.tsx b/src/screens/SignInScreen.tsx index d156352e..8ab95244 100644 --- a/src/screens/SignInScreen.tsx +++ b/src/screens/SignInScreen.tsx @@ -52,15 +52,15 @@ export const SignInScreen = (): JSX.Element => { enterKeyHint="next" inputMode="email" isRequired - label={t('common.email_label')} + label={t('form.labels.email')} name="email" onSubmitEditing={focusPasswordInput} - placeholder={t('common.email_placeholder')} + placeholder={t('form.placeholders.email')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), pattern: { value: REGEX.EMAIL, - message: t('form.invalid_email_format'), + message: t('form.validation.invalid_email_format'), }, }} testID="emailInput" @@ -70,12 +70,12 @@ export const SignInScreen = (): JSX.Element => { autoCapitalize="none" enterKeyHint="send" isRequired - label={t('sign_in_screen.password_label')} + label={t('form.labels.password')} name="password" onSubmitEditing={submit} - placeholder={t('sign_in_screen.password_placeholder')} + placeholder={t('form.placeholders.password')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} testID="passwordInput" type="password" diff --git a/src/screens/SignUpScreen.tsx b/src/screens/SignUpScreen.tsx index 50ed8a45..1c8f30ac 100644 --- a/src/screens/SignUpScreen.tsx +++ b/src/screens/SignUpScreen.tsx @@ -30,13 +30,13 @@ export const SignUpScreen = () => { autoCapitalize="none" enterKeyHint="next" isRequired - label={t('sign_up_screen.first_name_label')} + label={t('form.labels.first_name')} mb={2} name="firstName" onSubmitEditing={focusLastNameInput} - placeholder={t('sign_up_screen.first_name_placeholder')} + placeholder={t('form.placeholders.first_name')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} /> { autoCapitalize="none" enterKeyHint="next" isRequired - label={t('sign_up_screen.last_name_label')} + label={t('form.labels.last_name')} mb={2} name="lastName" onSubmitEditing={focusEmailInput} - placeholder={t('sign_up_screen.last_name_placeholder')} + placeholder={t('form.placeholders.last_name')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} /> { enterKeyHint="next" inputMode="email" isRequired - label={t('sign_up_screen.email_label')} + label={t('form.labels.email')} mb={2} name="email" onSubmitEditing={focusPasswordInput} - placeholder={t('sign_up_screen.email_placeholder')} + placeholder={t('form.placeholders.email')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} /> { autoCapitalize="none" enterKeyHint="next" isRequired - label={t('sign_up_screen.password_label')} + label={t('form.labels.password')} mb={16} name="password" onSubmitEditing={register} - placeholder={t('sign_up_screen.password_placeholder')} + placeholder={t('form.placeholders.create_password')} rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} type="password" /> @@ -90,7 +90,7 @@ export const SignUpScreen = () => { isRequired name="privacyPolicyAccepted" rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} size={18} /> @@ -100,7 +100,7 @@ export const SignUpScreen = () => { isRequired name="termsAccepted" rules={{ - required: t('form.required'), + required: t('form.validation.required'), }} size={18} /> diff --git a/src/utils/getApiError.ts b/src/utils/getApiError.ts index a3cf17ef..fd6bae3b 100644 --- a/src/utils/getApiError.ts +++ b/src/utils/getApiError.ts @@ -2,8 +2,8 @@ import i18n from '../i18n' //CONFIG: This are examples errors, change it export const API_ERRORS = [ - { errorMessage: 'invalidPassword', translation: i18n.t('form.invalid_password') }, - { errorMessage: 'ERROR.INCORRECT.EMAIL', translation: i18n.t('form.invalid_email_format') }, + { errorMessage: 'invalidPassword', translation: i18n.t('errors.invalid_password') }, + { errorMessage: 'ERROR.INCORRECT.EMAIL', translation: i18n.t('errors.invalid_email') }, { errorMessage: 'Token invalid', translation: i18n.t('errors.token_expired') }, { errorMessage: 'Missing authentication', translation: i18n.t('errors.missing_auth') }, ] From f78c94528c82675ed4e04e8b5d27ea8a630e11c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Baumruck?= Date: Thu, 14 Mar 2024 10:59:48 +0100 Subject: [PATCH 13/14] clean up some translations --- src/hooks/forms/useSignUpForm.ts | 2 +- src/hooks/forms/useUpdateProfileForm.ts | 2 +- src/i18n/translations/en.json | 29 +++++++++++++------------ src/i18n/translations/pl.json | 29 +++++++++++++------------ src/screens/SignInScreen.tsx | 2 +- src/screens/SignUpScreen.tsx | 4 ++-- 6 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/hooks/forms/useSignUpForm.ts b/src/hooks/forms/useSignUpForm.ts index 6640d1e3..2ab5f42b 100644 --- a/src/hooks/forms/useSignUpForm.ts +++ b/src/hooks/forms/useSignUpForm.ts @@ -43,7 +43,7 @@ export const useSignUpForm = () => { params: { style: { multiline: 100 }, title: 'SUCCESS', - description: t('sign_up_screen.created_new_account', { userEmail: data.email }), + description: t('toast.success.new_account_created', { userEmail: data.email }), }, }) }, diff --git a/src/hooks/forms/useUpdateProfileForm.ts b/src/hooks/forms/useUpdateProfileForm.ts index 1751a63c..b8b98618 100644 --- a/src/hooks/forms/useUpdateProfileForm.ts +++ b/src/hooks/forms/useUpdateProfileForm.ts @@ -46,7 +46,7 @@ export const useUpdateProfileForm = () => { params: { style: { multiline: 100 }, title: 'SUCCESS', - description: t('profile_screen.update_profile_success'), + description: t('toast.success.profile_updated'), }, }) }, diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json index 62c3fc29..6fabeca1 100644 --- a/src/i18n/translations/en.json +++ b/src/i18n/translations/en.json @@ -22,6 +22,11 @@ "example": "Example" }, "form": { + "checkbox": { + "privacy_policy": "I’ve read and accept Privacy Policy", + "remember_me": "Remember me", + "terms_accepted": "I agree to the Terms and Conditions" + }, "errors": {}, "labels": { "email": "E-mail address", @@ -36,6 +41,7 @@ "last_name": "Enter your last name", "password": "Password" }, + "select": {}, "validation": { "invalid_email_format": "Incorrect e-mail address format", "invalid_password_format": "Password must be at least 8 characters long, contain at least one uppercase letter, one lowercase letter, one number, and one special character", @@ -69,6 +75,14 @@ "typography": "Typography" } }, + "toast": { + "error": {}, + "success": { + "new_account_created": "A new account has been created. An email with an activation link was sent to {{userEmail}}.", + "profile_updated": "Successfully updated your profile data." + }, + "warning": {} + }, "update": { "alert_message": "You will have to restart the application to have better experiences while using it", "alert_title": "New version available", @@ -145,9 +159,6 @@ "login_cta": "Log in", "sign_up": "Sign up" }, - "profile_screen": { - "update_profile_success": "Successfully updated your data." - }, "settings_screen": { "copy_push_token": "Copy push token", "current_theme": "Current theme: {{theme}}", @@ -156,21 +167,11 @@ }, "sign_in_screen": { "do_not_have_an_account": "Don't have an account?", - "email_helper_text": "Email must be here", - "forgot_password": "Forgot your password?", - "or_pass": "or enter:", - "password_helper_text": "Password must be here", - "remember_me": "Remember me", "sign_in": "Sign in", "sign_up": "Sign up" }, "sign_up_screen": { - "created_new_account": "A new account has been created. An email with an activation link was sent to {{userEmail}}.", - "newsletter_label": "Subscribe to our newsletter", - "privacy_policy_label": "I’ve read and accept Privacy Policy", - "sign_up": "Sign up", - "terms_accepted_label": "I agree to the Terms and Conditions", - "trail_description": "Start your 30-day free trial." + "sign_up": "Sign up" }, "test_form": { "additional_comment": "Additional comment", diff --git a/src/i18n/translations/pl.json b/src/i18n/translations/pl.json index 7b0aa781..73c882f4 100644 --- a/src/i18n/translations/pl.json +++ b/src/i18n/translations/pl.json @@ -22,6 +22,11 @@ "example": "Przykład" }, "form": { + "checkbox": { + "privacy_policy": "Zapoznałem się i akceptuję politykę prywatności", + "remember_me": "Zapamiętaj mnie", + "terms_accepted": "Zgadzam się z warunkami użytkowania" + }, "errors": {}, "labels": { "email": "Adres e-mail", @@ -36,6 +41,7 @@ "last_name": "Podaj swoje nazwisko", "password": "Hasło" }, + "select": {}, "validation": { "invalid_email_format": "Niepoprawny format adresu e-mail", "invalid_password_format": "Hasło musi zawierać minimum: 8 znaków, jedną wielką literę, jedną małą literę, jedną cyfrę i jeden znak specjalny", @@ -69,6 +75,14 @@ "typography": "Typography" } }, + "toast": { + "error": {}, + "success": { + "new_account_created": "Nowe konto zostało stworzone. Email z linkiem weryfikacyjnym został wysłany na {{userEmail}}.", + "profile_updated": "Zaktualizowano Twoje dane." + }, + "warning": {} + }, "update": { "alert_message": "Będziesz musiał zrestartować aplikację, żeby mieć lepsze doświadczenia podczas jej używania", "alert_title": "Aktualizacja", @@ -144,9 +158,6 @@ "go_to_blog": "Otwórz blog", "go_to_form": "Otwórz pełno ekranowy formularz full" }, - "profile_screen": { - "update_profile_success": "Poprawnie zaktualizowano Twoje dane." - }, "settings_screen": { "current_theme": "Current theme: {{theme}}", "selected": " - wybrano", @@ -154,22 +165,12 @@ }, "sign_in_screen": { "do_not_have_an_account": "Nie masz konta?", - "email_helper_text": "Email", - "forgot_password": "Zapomniałeś hasła?", - "or_pass": "lub wprowadź:", - "password_helper_text": "Hasła muszą być takie same", - "remember_me": "Zapamiętaj mnie", "sign_in": "Zaloguj", "sign_up": "Zarejestruj" }, "sign_up_screen": { "created_new_account": "Nowe konto zostało stworzone. Email z linkiem weryfikacyjnym został wysłany na {{userEmail}}.", - "newsletter_label": "Subskrybuj nasz newsletter", - "password_label": "Hasło", - "privacy_policy_label": "Zapoznałem się i akceptuję politykę prywatności", - "sign_up": "Zarejestruj", - "terms_accepted_label": "Zgadzam się z warunkami użytkowania", - "trail_description": "Rozpocznij darmowy 30 dniowy okres próbny." + "sign_up": "Zarejestruj" }, "test_form": { "additional_comment": "Dodatkowy komentarz", diff --git a/src/screens/SignInScreen.tsx b/src/screens/SignInScreen.tsx index 8ab95244..ad621289 100644 --- a/src/screens/SignInScreen.tsx +++ b/src/screens/SignInScreen.tsx @@ -83,7 +83,7 @@ export const SignInScreen = (): JSX.Element => {
{ { /> Date: Thu, 14 Mar 2024 11:02:47 +0100 Subject: [PATCH 14/14] rename sing up mutation fn --- src/hooks/forms/useSignUpForm.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/forms/useSignUpForm.ts b/src/hooks/forms/useSignUpForm.ts index 2ab5f42b..6b86e218 100644 --- a/src/hooks/forms/useSignUpForm.ts +++ b/src/hooks/forms/useSignUpForm.ts @@ -18,7 +18,7 @@ const defaultValues: AuthRegisterLoginDto = { } export const useSignUpForm = () => { - const { mutate: loginMutation, isLoading } = useAuthControllerRegister() + const { mutate: signUpMutation, isLoading } = useAuthControllerRegister() const { t } = useTranslation() const { @@ -33,7 +33,7 @@ export const useSignUpForm = () => { }) const onSubmit = (data: AuthRegisterLoginDto) => { - loginMutation( + signUpMutation( { data, },