From 9445f0cecfcfcd13ae0ad027d0f9380d13b683be Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 01:28:38 +0300 Subject: [PATCH 01/73] chore: install dependencies --- src/client/package.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/client/package.json b/src/client/package.json index 2273591..ccca508 100644 --- a/src/client/package.json +++ b/src/client/package.json @@ -7,6 +7,10 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", + "@types/jest": "^29.5.2", + "@types/node": "^20.2.5", + "@types/react": "^18.2.8", + "@types/react-dom": "^18.2.4", "http-proxy-middleware": "^2.0.6", "prop-types": "^15.8.1", "react": "^18.2.0", @@ -14,6 +18,7 @@ "react-redux": "^8.0.5", "react-router-dom": "^6.6.2", "react-scripts": "5.0.1", + "typescript": "^5.1.3", "web-vitals": "^2.1.4" }, "scripts": { From d1bbb7a7fa2fbdd089d8654325677f2d78dd5945 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 01:30:17 +0300 Subject: [PATCH 02/73] chore: init tsconfig --- src/client/tsconfig.json | 109 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/client/tsconfig.json diff --git a/src/client/tsconfig.json b/src/client/tsconfig.json new file mode 100644 index 0000000..bc58db3 --- /dev/null +++ b/src/client/tsconfig.json @@ -0,0 +1,109 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} From 2252a62edb4b2a0ab40738f8d2c0faca3c5675c1 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 01:40:52 +0300 Subject: [PATCH 03/73] chore: install typescript deps --- src/client/package.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/client/package.json b/src/client/package.json index ccca508..1aa0afd 100644 --- a/src/client/package.json +++ b/src/client/package.json @@ -21,6 +21,11 @@ "typescript": "^5.1.3", "web-vitals": "^2.1.4" }, + "overrides": { + "react-scripts": { + "typescript": ">3.2.1" + } + }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", @@ -44,5 +49,10 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^5.59.9", + "@typescript-eslint/parser": "^5.59.9", + "eslint": "^8.42.0" } } From fcd9bb766d7484d715acf9e005f8db1fb818c928 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 01:41:11 +0300 Subject: [PATCH 04/73] chore: add typescript rules to eslint --- src/client/.eslintrc.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/client/.eslintrc.json b/src/client/.eslintrc.json index 7050097..408a21a 100644 --- a/src/client/.eslintrc.json +++ b/src/client/.eslintrc.json @@ -4,7 +4,11 @@ "es6": true, "node": true }, - "extends": ["eslint:recommended", "plugin:react/recommended"], + "plugins": [ + "@typescript-eslint" +], + "extends": ["eslint:recommended", "plugin:react/recommended", "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended"], "parserOptions": { "ecmaVersion": 2020, "sourceType": "module" From 3806ffabf6fde3c9d137a1e5562eee64157c82a0 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 01:41:22 +0300 Subject: [PATCH 05/73] chore: add ignore to file --- src/client/src/setupProxy.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/client/src/setupProxy.js b/src/client/src/setupProxy.js index edb6f2c..430c377 100644 --- a/src/client/src/setupProxy.js +++ b/src/client/src/setupProxy.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires const { createProxyMiddleware } = require('http-proxy-middleware'); import * as dotenv from 'dotenv'; dotenv.config(); From baee963586ceb0fa7018e36d1828a780919769d2 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 01:49:22 +0300 Subject: [PATCH 06/73] refactor: change file extensions to tsx --- src/client/src/{App.jsx => App.tsx} | 0 .../account/{addFavoriteRecipe.js => addFavoriteRecipe.ts} | 0 .../account/{deleteFavoriteRecipe.js => deleteFavoriteRecipe.ts} | 0 .../account/{loadFavoriteRecipes.js => loadFavoriteRecipes.ts} | 0 src/client/src/app/actions/account/{loginUser.js => loginUser.ts} | 0 .../src/app/actions/account/{registerUser.js => registerUser.ts} | 0 src/client/src/app/slices/{accountSlice.js => accountSlice.ts} | 0 src/client/src/app/slices/{recipesSlice.js => recipesSlice.ts} | 0 src/client/src/app/{store.js => store.ts} | 0 .../src/app/utils/{thunkErrorWrapper.js => thunkErrorWrapper.ts} | 0 src/client/src/components/{Banner.jsx => Banner.tsx} | 0 src/client/src/components/{ErrorMessage.jsx => ErrorMessage.tsx} | 0 src/client/src/components/{Footer.jsx => Footer.tsx} | 0 src/client/src/components/{Header.jsx => Header.tsx} | 0 src/client/src/components/{Loader.jsx => Loader.tsx} | 0 src/client/src/components/{Recipe.jsx => Recipe.tsx} | 0 src/client/src/components/{Search.jsx => Search.tsx} | 0 src/client/src/features/{AppRoutes.js => AppRoutes.ts} | 0 .../src/features/{ProtectedRoute.jsx => ProtectedRoute.tsx} | 0 .../src/features/{ValidationError.js => ValidationError.ts} | 0 src/client/src/{index.js => index.tsx} | 0 src/client/src/pages/{Home.jsx => Home.tsx} | 0 src/client/src/pages/{Login.jsx => Login.tsx} | 0 src/client/src/pages/{RecipePage.jsx => RecipePage.tsx} | 0 src/client/src/pages/{Register.jsx => Register.tsx} | 0 src/client/src/pages/{SearchRecipes.jsx => SearchRecipes.tsx} | 0 src/client/src/pages/{User.jsx => User.tsx} | 0 src/client/src/services/{AuthService.js => AuthService.ts} | 0 src/client/src/services/{BaseService.js => BaseService.ts} | 0 src/client/src/services/{RecipeService.js => RecipeService.ts} | 0 src/client/src/services/{UserService.js => UserService.ts} | 0 src/client/src/services/errors/{AuthError.js => AuthError.ts} | 0 src/client/src/services/errors/{BaseError.js => BaseError.ts} | 0 src/client/src/services/errors/{RecipeError.js => RecipeError.ts} | 0 src/client/src/services/errors/{UserError.js => UserError.ts} | 0 35 files changed, 0 insertions(+), 0 deletions(-) rename src/client/src/{App.jsx => App.tsx} (100%) rename src/client/src/app/actions/account/{addFavoriteRecipe.js => addFavoriteRecipe.ts} (100%) rename src/client/src/app/actions/account/{deleteFavoriteRecipe.js => deleteFavoriteRecipe.ts} (100%) rename src/client/src/app/actions/account/{loadFavoriteRecipes.js => loadFavoriteRecipes.ts} (100%) rename src/client/src/app/actions/account/{loginUser.js => loginUser.ts} (100%) rename src/client/src/app/actions/account/{registerUser.js => registerUser.ts} (100%) rename src/client/src/app/slices/{accountSlice.js => accountSlice.ts} (100%) rename src/client/src/app/slices/{recipesSlice.js => recipesSlice.ts} (100%) rename src/client/src/app/{store.js => store.ts} (100%) rename src/client/src/app/utils/{thunkErrorWrapper.js => thunkErrorWrapper.ts} (100%) rename src/client/src/components/{Banner.jsx => Banner.tsx} (100%) rename src/client/src/components/{ErrorMessage.jsx => ErrorMessage.tsx} (100%) rename src/client/src/components/{Footer.jsx => Footer.tsx} (100%) rename src/client/src/components/{Header.jsx => Header.tsx} (100%) rename src/client/src/components/{Loader.jsx => Loader.tsx} (100%) rename src/client/src/components/{Recipe.jsx => Recipe.tsx} (100%) rename src/client/src/components/{Search.jsx => Search.tsx} (100%) rename src/client/src/features/{AppRoutes.js => AppRoutes.ts} (100%) rename src/client/src/features/{ProtectedRoute.jsx => ProtectedRoute.tsx} (100%) rename src/client/src/features/{ValidationError.js => ValidationError.ts} (100%) rename src/client/src/{index.js => index.tsx} (100%) rename src/client/src/pages/{Home.jsx => Home.tsx} (100%) rename src/client/src/pages/{Login.jsx => Login.tsx} (100%) rename src/client/src/pages/{RecipePage.jsx => RecipePage.tsx} (100%) rename src/client/src/pages/{Register.jsx => Register.tsx} (100%) rename src/client/src/pages/{SearchRecipes.jsx => SearchRecipes.tsx} (100%) rename src/client/src/pages/{User.jsx => User.tsx} (100%) rename src/client/src/services/{AuthService.js => AuthService.ts} (100%) rename src/client/src/services/{BaseService.js => BaseService.ts} (100%) rename src/client/src/services/{RecipeService.js => RecipeService.ts} (100%) rename src/client/src/services/{UserService.js => UserService.ts} (100%) rename src/client/src/services/errors/{AuthError.js => AuthError.ts} (100%) rename src/client/src/services/errors/{BaseError.js => BaseError.ts} (100%) rename src/client/src/services/errors/{RecipeError.js => RecipeError.ts} (100%) rename src/client/src/services/errors/{UserError.js => UserError.ts} (100%) diff --git a/src/client/src/App.jsx b/src/client/src/App.tsx similarity index 100% rename from src/client/src/App.jsx rename to src/client/src/App.tsx diff --git a/src/client/src/app/actions/account/addFavoriteRecipe.js b/src/client/src/app/actions/account/addFavoriteRecipe.ts similarity index 100% rename from src/client/src/app/actions/account/addFavoriteRecipe.js rename to src/client/src/app/actions/account/addFavoriteRecipe.ts diff --git a/src/client/src/app/actions/account/deleteFavoriteRecipe.js b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts similarity index 100% rename from src/client/src/app/actions/account/deleteFavoriteRecipe.js rename to src/client/src/app/actions/account/deleteFavoriteRecipe.ts diff --git a/src/client/src/app/actions/account/loadFavoriteRecipes.js b/src/client/src/app/actions/account/loadFavoriteRecipes.ts similarity index 100% rename from src/client/src/app/actions/account/loadFavoriteRecipes.js rename to src/client/src/app/actions/account/loadFavoriteRecipes.ts diff --git a/src/client/src/app/actions/account/loginUser.js b/src/client/src/app/actions/account/loginUser.ts similarity index 100% rename from src/client/src/app/actions/account/loginUser.js rename to src/client/src/app/actions/account/loginUser.ts diff --git a/src/client/src/app/actions/account/registerUser.js b/src/client/src/app/actions/account/registerUser.ts similarity index 100% rename from src/client/src/app/actions/account/registerUser.js rename to src/client/src/app/actions/account/registerUser.ts diff --git a/src/client/src/app/slices/accountSlice.js b/src/client/src/app/slices/accountSlice.ts similarity index 100% rename from src/client/src/app/slices/accountSlice.js rename to src/client/src/app/slices/accountSlice.ts diff --git a/src/client/src/app/slices/recipesSlice.js b/src/client/src/app/slices/recipesSlice.ts similarity index 100% rename from src/client/src/app/slices/recipesSlice.js rename to src/client/src/app/slices/recipesSlice.ts diff --git a/src/client/src/app/store.js b/src/client/src/app/store.ts similarity index 100% rename from src/client/src/app/store.js rename to src/client/src/app/store.ts diff --git a/src/client/src/app/utils/thunkErrorWrapper.js b/src/client/src/app/utils/thunkErrorWrapper.ts similarity index 100% rename from src/client/src/app/utils/thunkErrorWrapper.js rename to src/client/src/app/utils/thunkErrorWrapper.ts diff --git a/src/client/src/components/Banner.jsx b/src/client/src/components/Banner.tsx similarity index 100% rename from src/client/src/components/Banner.jsx rename to src/client/src/components/Banner.tsx diff --git a/src/client/src/components/ErrorMessage.jsx b/src/client/src/components/ErrorMessage.tsx similarity index 100% rename from src/client/src/components/ErrorMessage.jsx rename to src/client/src/components/ErrorMessage.tsx diff --git a/src/client/src/components/Footer.jsx b/src/client/src/components/Footer.tsx similarity index 100% rename from src/client/src/components/Footer.jsx rename to src/client/src/components/Footer.tsx diff --git a/src/client/src/components/Header.jsx b/src/client/src/components/Header.tsx similarity index 100% rename from src/client/src/components/Header.jsx rename to src/client/src/components/Header.tsx diff --git a/src/client/src/components/Loader.jsx b/src/client/src/components/Loader.tsx similarity index 100% rename from src/client/src/components/Loader.jsx rename to src/client/src/components/Loader.tsx diff --git a/src/client/src/components/Recipe.jsx b/src/client/src/components/Recipe.tsx similarity index 100% rename from src/client/src/components/Recipe.jsx rename to src/client/src/components/Recipe.tsx diff --git a/src/client/src/components/Search.jsx b/src/client/src/components/Search.tsx similarity index 100% rename from src/client/src/components/Search.jsx rename to src/client/src/components/Search.tsx diff --git a/src/client/src/features/AppRoutes.js b/src/client/src/features/AppRoutes.ts similarity index 100% rename from src/client/src/features/AppRoutes.js rename to src/client/src/features/AppRoutes.ts diff --git a/src/client/src/features/ProtectedRoute.jsx b/src/client/src/features/ProtectedRoute.tsx similarity index 100% rename from src/client/src/features/ProtectedRoute.jsx rename to src/client/src/features/ProtectedRoute.tsx diff --git a/src/client/src/features/ValidationError.js b/src/client/src/features/ValidationError.ts similarity index 100% rename from src/client/src/features/ValidationError.js rename to src/client/src/features/ValidationError.ts diff --git a/src/client/src/index.js b/src/client/src/index.tsx similarity index 100% rename from src/client/src/index.js rename to src/client/src/index.tsx diff --git a/src/client/src/pages/Home.jsx b/src/client/src/pages/Home.tsx similarity index 100% rename from src/client/src/pages/Home.jsx rename to src/client/src/pages/Home.tsx diff --git a/src/client/src/pages/Login.jsx b/src/client/src/pages/Login.tsx similarity index 100% rename from src/client/src/pages/Login.jsx rename to src/client/src/pages/Login.tsx diff --git a/src/client/src/pages/RecipePage.jsx b/src/client/src/pages/RecipePage.tsx similarity index 100% rename from src/client/src/pages/RecipePage.jsx rename to src/client/src/pages/RecipePage.tsx diff --git a/src/client/src/pages/Register.jsx b/src/client/src/pages/Register.tsx similarity index 100% rename from src/client/src/pages/Register.jsx rename to src/client/src/pages/Register.tsx diff --git a/src/client/src/pages/SearchRecipes.jsx b/src/client/src/pages/SearchRecipes.tsx similarity index 100% rename from src/client/src/pages/SearchRecipes.jsx rename to src/client/src/pages/SearchRecipes.tsx diff --git a/src/client/src/pages/User.jsx b/src/client/src/pages/User.tsx similarity index 100% rename from src/client/src/pages/User.jsx rename to src/client/src/pages/User.tsx diff --git a/src/client/src/services/AuthService.js b/src/client/src/services/AuthService.ts similarity index 100% rename from src/client/src/services/AuthService.js rename to src/client/src/services/AuthService.ts diff --git a/src/client/src/services/BaseService.js b/src/client/src/services/BaseService.ts similarity index 100% rename from src/client/src/services/BaseService.js rename to src/client/src/services/BaseService.ts diff --git a/src/client/src/services/RecipeService.js b/src/client/src/services/RecipeService.ts similarity index 100% rename from src/client/src/services/RecipeService.js rename to src/client/src/services/RecipeService.ts diff --git a/src/client/src/services/UserService.js b/src/client/src/services/UserService.ts similarity index 100% rename from src/client/src/services/UserService.js rename to src/client/src/services/UserService.ts diff --git a/src/client/src/services/errors/AuthError.js b/src/client/src/services/errors/AuthError.ts similarity index 100% rename from src/client/src/services/errors/AuthError.js rename to src/client/src/services/errors/AuthError.ts diff --git a/src/client/src/services/errors/BaseError.js b/src/client/src/services/errors/BaseError.ts similarity index 100% rename from src/client/src/services/errors/BaseError.js rename to src/client/src/services/errors/BaseError.ts diff --git a/src/client/src/services/errors/RecipeError.js b/src/client/src/services/errors/RecipeError.ts similarity index 100% rename from src/client/src/services/errors/RecipeError.js rename to src/client/src/services/errors/RecipeError.ts diff --git a/src/client/src/services/errors/UserError.js b/src/client/src/services/errors/UserError.ts similarity index 100% rename from src/client/src/services/errors/UserError.js rename to src/client/src/services/errors/UserError.ts From 3c785f18220c6b1af82a3d1f08e6f663ea793b8f Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 02:00:41 +0300 Subject: [PATCH 07/73] chore: update tsconfig --- src/client/tsconfig.json | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/client/tsconfig.json b/src/client/tsconfig.json index bc58db3..a621af3 100644 --- a/src/client/tsconfig.json +++ b/src/client/tsconfig.json @@ -12,7 +12,11 @@ /* Language and Environment */ "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ @@ -25,9 +29,9 @@ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ + "module": "esnext", /* Specify what module code is generated. */ // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ @@ -39,12 +43,12 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ + "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ @@ -57,7 +61,7 @@ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ // "outDir": "./", /* Specify an output folder for all emitted files. */ // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ + "noEmit": true, /* Disable emitting files from a compilation. */ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ @@ -74,9 +78,9 @@ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ @@ -95,7 +99,7 @@ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ @@ -104,6 +108,12 @@ /* Completeness */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } + "skipLibCheck": true, + /* Skip type checking all .d.ts files. */ + "jsx": "react" + }, + "include": [ + "src", + "custom.d.ts" +] } From 8354bfc8e0cf9aef4a53340230d7cdd834616892 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 02:00:58 +0300 Subject: [PATCH 08/73] refactor: change extension --- src/client/src/{reportWebVitals.js => reportWebVitals.ts} | 6 ++++-- src/client/src/{setupProxy.js => setupProxy.ts} | 0 src/client/src/{setupTests.js => setupTests.ts} | 0 3 files changed, 4 insertions(+), 2 deletions(-) rename src/client/src/{reportWebVitals.js => reportWebVitals.ts} (67%) rename src/client/src/{setupProxy.js => setupProxy.ts} (100%) rename src/client/src/{setupTests.js => setupTests.ts} (100%) diff --git a/src/client/src/reportWebVitals.js b/src/client/src/reportWebVitals.ts similarity index 67% rename from src/client/src/reportWebVitals.js rename to src/client/src/reportWebVitals.ts index 5253d3a..cfad7f0 100644 --- a/src/client/src/reportWebVitals.js +++ b/src/client/src/reportWebVitals.ts @@ -1,5 +1,7 @@ -const reportWebVitals = onPerfEntry => { - if (onPerfEntry && onPerfEntry instanceof Function) { +import { ReportHandler } from 'web-vitals'; + +const reportWebVitals = (onPerfEntry?: ReportHandler) => { + if (onPerfEntry) { import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { getCLS(onPerfEntry); getFID(onPerfEntry); diff --git a/src/client/src/setupProxy.js b/src/client/src/setupProxy.ts similarity index 100% rename from src/client/src/setupProxy.js rename to src/client/src/setupProxy.ts diff --git a/src/client/src/setupTests.js b/src/client/src/setupTests.ts similarity index 100% rename from src/client/src/setupTests.js rename to src/client/src/setupTests.ts From d32cb381cb03be91cda0c89399166537a5cf7e4e Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 02:01:13 +0300 Subject: [PATCH 09/73] refactor: add as HTMLElement --- src/client/src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/index.tsx b/src/client/src/index.tsx index d50b235..baf0c4a 100644 --- a/src/client/src/index.tsx +++ b/src/client/src/index.tsx @@ -7,7 +7,7 @@ import reportWebVitals from './reportWebVitals'; import './index.css'; import { BrowserRouter } from 'react-router-dom'; -const container = document.getElementById('root'); +const container = document.getElementById('root') as HTMLElement; const root = createRoot(container); root.render( From 293109799931807f2bc18559212d1e8cb1fa1765 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 02:02:39 +0300 Subject: [PATCH 10/73] refactor: add ts types to store --- src/client/src/app/store.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/client/src/app/store.ts b/src/client/src/app/store.ts index 948cf7f..c934553 100644 --- a/src/client/src/app/store.ts +++ b/src/client/src/app/store.ts @@ -1,9 +1,10 @@ -import { combineReducers, configureStore } from '@reduxjs/toolkit'; +import { Action, combineReducers, configureStore, ThunkAction } from '@reduxjs/toolkit'; import accountReducer from './slices/accountSlice'; import recipesReducer from './slices/recipesSlice'; import AuthService from '../services/AuthService'; import RecipeService from '../services/RecipeService'; import { thunkErrorWrapper } from './utils/thunkErrorWrapper'; +import { useDispatch } from 'react-redux'; const recipeService = new RecipeService(process.env.BASE_URL); const authService = new AuthService(process.env.BASE_URL); @@ -25,3 +26,13 @@ const store = configureStore({ }); export { store, recipeService, authService }; +export type AppDispatch = typeof store.dispatch; +export const useAppDispatch: () => AppDispatch = useDispatch; +export type RootState = ReturnType; +export type AppThunk = ThunkAction< + ReturnType, + RootState, + unknown, + Action +>; +export default store; From 5e75ce47e67ed7c7f3c02698024eb174f2630153 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 02:09:22 +0300 Subject: [PATCH 11/73] refactor: add useAppSelectorHook --- src/client/src/app/store.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/client/src/app/store.ts b/src/client/src/app/store.ts index c934553..6d79243 100644 --- a/src/client/src/app/store.ts +++ b/src/client/src/app/store.ts @@ -4,7 +4,7 @@ import recipesReducer from './slices/recipesSlice'; import AuthService from '../services/AuthService'; import RecipeService from '../services/RecipeService'; import { thunkErrorWrapper } from './utils/thunkErrorWrapper'; -import { useDispatch } from 'react-redux'; +import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; const recipeService = new RecipeService(process.env.BASE_URL); const authService = new AuthService(process.env.BASE_URL); @@ -27,8 +27,10 @@ const store = configureStore({ export { store, recipeService, authService }; export type AppDispatch = typeof store.dispatch; -export const useAppDispatch: () => AppDispatch = useDispatch; export type RootState = ReturnType; +export const useAppDispatch: () => AppDispatch = useDispatch; +export const useAppSelector: TypedUseSelectorHook = useSelector; + export type AppThunk = ThunkAction< ReturnType, RootState, From 502826b928924ccffd4aeac0d834ffff2abdd161 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 02:39:49 +0300 Subject: [PATCH 12/73] feat: created models types --- src/client/src/services/models/Recipe.ts | 8 ++++++++ src/client/src/services/models/User.ts | 4 ++++ 2 files changed, 12 insertions(+) create mode 100644 src/client/src/services/models/Recipe.ts create mode 100644 src/client/src/services/models/User.ts diff --git a/src/client/src/services/models/Recipe.ts b/src/client/src/services/models/Recipe.ts new file mode 100644 index 0000000..e905a14 --- /dev/null +++ b/src/client/src/services/models/Recipe.ts @@ -0,0 +1,8 @@ + + +export interface Recipe { + id: number, + name: string, + image_link: string, + products: string, +} diff --git a/src/client/src/services/models/User.ts b/src/client/src/services/models/User.ts new file mode 100644 index 0000000..48dcde5 --- /dev/null +++ b/src/client/src/services/models/User.ts @@ -0,0 +1,4 @@ +export interface User { + id: number; + username: string; +} From c953bf53339b7de8504a64145cb2516711093d65 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 02:40:10 +0300 Subject: [PATCH 13/73] feat: created types for store states --- src/client/src/app/slices/types/AuthFulfilled.ts | 6 ++++++ src/client/src/app/slices/types/AuthState.ts | 10 ++++++++++ src/client/src/app/slices/types/RecipeState.ts | 7 +++++++ 3 files changed, 23 insertions(+) create mode 100644 src/client/src/app/slices/types/AuthFulfilled.ts create mode 100644 src/client/src/app/slices/types/AuthState.ts create mode 100644 src/client/src/app/slices/types/RecipeState.ts diff --git a/src/client/src/app/slices/types/AuthFulfilled.ts b/src/client/src/app/slices/types/AuthFulfilled.ts new file mode 100644 index 0000000..951ea23 --- /dev/null +++ b/src/client/src/app/slices/types/AuthFulfilled.ts @@ -0,0 +1,6 @@ +import { User } from '../../../services/models/User'; + +export interface AuthFulfilled { + user: User, + accessToken: string, +} diff --git a/src/client/src/app/slices/types/AuthState.ts b/src/client/src/app/slices/types/AuthState.ts new file mode 100644 index 0000000..cce3fe6 --- /dev/null +++ b/src/client/src/app/slices/types/AuthState.ts @@ -0,0 +1,10 @@ +import { User } from '../../../services/models/User'; +import { Recipe } from '../../../services/models/Recipe'; + +export interface AuthState { + user: User | null, + token: string | null, + userRecipes: Recipe[], + loading: boolean, + error: string | null +} diff --git a/src/client/src/app/slices/types/RecipeState.ts b/src/client/src/app/slices/types/RecipeState.ts new file mode 100644 index 0000000..a22bb89 --- /dev/null +++ b/src/client/src/app/slices/types/RecipeState.ts @@ -0,0 +1,7 @@ +import { Recipe } from '../../../services/models/Recipe'; + +export interface RecipeState { + recipes: Recipe[], + loading: boolean, + error: Error | null, +} From 37725df757f2667027de60bbe387992360c0913c Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 02:40:50 +0300 Subject: [PATCH 14/73] refactor: change extension --- .../src/app/actions/recipes/{loadRecipes.js => loadRecipes.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/client/src/app/actions/recipes/{loadRecipes.js => loadRecipes.ts} (100%) diff --git a/src/client/src/app/actions/recipes/loadRecipes.js b/src/client/src/app/actions/recipes/loadRecipes.ts similarity index 100% rename from src/client/src/app/actions/recipes/loadRecipes.js rename to src/client/src/app/actions/recipes/loadRecipes.ts From 0cc8bb78e4b390a5fe5ce63b0ffd7dbdb0da4726 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 03:22:47 +0300 Subject: [PATCH 15/73] feat: created UserDTO --- src/client/src/services/DTO/UserDTO.ts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/client/src/services/DTO/UserDTO.ts diff --git a/src/client/src/services/DTO/UserDTO.ts b/src/client/src/services/DTO/UserDTO.ts new file mode 100644 index 0000000..4ee649b --- /dev/null +++ b/src/client/src/services/DTO/UserDTO.ts @@ -0,0 +1,4 @@ +export interface UserDTO { + username: string, + password: string, +} From d52323087e98a74f40b2caee1525373f21b46e10 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 03:23:10 +0300 Subject: [PATCH 16/73] refactor: moved types to corresponding folders --- .../src/app/slices/types/{ => Auth}/AuthFulfilled.ts | 2 +- src/client/src/app/slices/types/Auth/AuthState.ts | 11 +++++++++++ src/client/src/app/slices/types/AuthState.ts | 10 ---------- src/client/src/app/slices/types/Recipe/RecipeState.ts | 8 ++++++++ src/client/src/app/slices/types/RecipeState.ts | 7 ------- 5 files changed, 20 insertions(+), 18 deletions(-) rename src/client/src/app/slices/types/{ => Auth}/AuthFulfilled.ts (56%) create mode 100644 src/client/src/app/slices/types/Auth/AuthState.ts delete mode 100644 src/client/src/app/slices/types/AuthState.ts create mode 100644 src/client/src/app/slices/types/Recipe/RecipeState.ts delete mode 100644 src/client/src/app/slices/types/RecipeState.ts diff --git a/src/client/src/app/slices/types/AuthFulfilled.ts b/src/client/src/app/slices/types/Auth/AuthFulfilled.ts similarity index 56% rename from src/client/src/app/slices/types/AuthFulfilled.ts rename to src/client/src/app/slices/types/Auth/AuthFulfilled.ts index 951ea23..9c9516b 100644 --- a/src/client/src/app/slices/types/AuthFulfilled.ts +++ b/src/client/src/app/slices/types/Auth/AuthFulfilled.ts @@ -1,4 +1,4 @@ -import { User } from '../../../services/models/User'; +import { User } from '../../../../services/models/User'; export interface AuthFulfilled { user: User, diff --git a/src/client/src/app/slices/types/Auth/AuthState.ts b/src/client/src/app/slices/types/Auth/AuthState.ts new file mode 100644 index 0000000..0ce5bd6 --- /dev/null +++ b/src/client/src/app/slices/types/Auth/AuthState.ts @@ -0,0 +1,11 @@ +import { User } from '../../../../services/models/User'; +import { Recipe } from '../../../../services/models/Recipe'; + +export type AuthError = string | Error | undefined | null; +export interface AuthState { + user: User | null, + token: string | null, + userRecipes: Recipe[], + loading: boolean, + error: AuthError +} diff --git a/src/client/src/app/slices/types/AuthState.ts b/src/client/src/app/slices/types/AuthState.ts deleted file mode 100644 index cce3fe6..0000000 --- a/src/client/src/app/slices/types/AuthState.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { User } from '../../../services/models/User'; -import { Recipe } from '../../../services/models/Recipe'; - -export interface AuthState { - user: User | null, - token: string | null, - userRecipes: Recipe[], - loading: boolean, - error: string | null -} diff --git a/src/client/src/app/slices/types/Recipe/RecipeState.ts b/src/client/src/app/slices/types/Recipe/RecipeState.ts new file mode 100644 index 0000000..203867d --- /dev/null +++ b/src/client/src/app/slices/types/Recipe/RecipeState.ts @@ -0,0 +1,8 @@ +import { Recipe } from '../../../../services/models/Recipe'; + +export type RecipeError = string | Error | null | undefined; +export interface RecipeState { + recipes: Recipe[], + loading: boolean, + error: RecipeError +} diff --git a/src/client/src/app/slices/types/RecipeState.ts b/src/client/src/app/slices/types/RecipeState.ts deleted file mode 100644 index a22bb89..0000000 --- a/src/client/src/app/slices/types/RecipeState.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Recipe } from '../../../services/models/Recipe'; - -export interface RecipeState { - recipes: Recipe[], - loading: boolean, - error: Error | null, -} From ac197c857381f71421586e816cdef56505aed2e8 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 03:23:27 +0300 Subject: [PATCH 17/73] feat: typed BaseService --- src/client/src/services/BaseService.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/client/src/services/BaseService.ts b/src/client/src/services/BaseService.ts index 5dd72fc..a3bdc75 100644 --- a/src/client/src/services/BaseService.ts +++ b/src/client/src/services/BaseService.ts @@ -2,16 +2,18 @@ import { useDispatch } from 'react-redux'; import { logout as storeLogout } from '../app/slices/accountSlice'; export default class BaseService { - constructor(baseURL) { + public token: string | null; + private readonly baseURL: string; + constructor(baseURL: string) { this.baseURL = baseURL; this.token = null; } - setToken(token) { + setToken(token: string | null) { this.token = token; } - async request(endpoint, method, body = {}) { + async request(endpoint: string, method: string, body = {}) { const url = `${this.baseURL}${endpoint}`; try { From 4394535070a989e0073c90b65769e2f4bdd3fabd Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 03:23:45 +0300 Subject: [PATCH 18/73] feat: typed thunkErrorWrapper --- src/client/src/app/utils/thunkErrorWrapper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/src/app/utils/thunkErrorWrapper.ts b/src/client/src/app/utils/thunkErrorWrapper.ts index ed23936..bc76514 100644 --- a/src/client/src/app/utils/thunkErrorWrapper.ts +++ b/src/client/src/app/utils/thunkErrorWrapper.ts @@ -1,11 +1,11 @@ -export const thunkErrorWrapper = (method, rejectWithValue, context = null) => async (...args) => { +export const thunkErrorWrapper = (method: any, rejectWithValue: any, context = null) => async (...args : any) => { try { const response = await method.apply(context, args); if (response.error) { return rejectWithValue(response.error); } return response; - } catch (error) { + } catch (error: any) { return rejectWithValue(error.response.data.message ?? error.message); } }; From c2da8d79f022f395d569dc6efe394c0f20171589 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 03:24:11 +0300 Subject: [PATCH 19/73] feat: added userService and createAppAsyncThunk --- src/client/src/app/store.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/client/src/app/store.ts b/src/client/src/app/store.ts index 6d79243..313fd4f 100644 --- a/src/client/src/app/store.ts +++ b/src/client/src/app/store.ts @@ -1,13 +1,16 @@ -import { Action, combineReducers, configureStore, ThunkAction } from '@reduxjs/toolkit'; +import { Action, combineReducers, configureStore, createAsyncThunk, ThunkAction } from '@reduxjs/toolkit'; import accountReducer from './slices/accountSlice'; import recipesReducer from './slices/recipesSlice'; import AuthService from '../services/AuthService'; import RecipeService from '../services/RecipeService'; import { thunkErrorWrapper } from './utils/thunkErrorWrapper'; import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; +import UserService from '../services/UserService'; const recipeService = new RecipeService(process.env.BASE_URL); const authService = new AuthService(process.env.BASE_URL); +const userService = new UserService(process.env.BASE_URL); + const rootReducer = combineReducers({ account: accountReducer, @@ -20,7 +23,7 @@ const store = configureStore({ middleware: getDefaultMiddleware => getDefaultMiddleware({ thunk: { - extraArgument: { recipeService, authService, thunkErrorWrapper }, + extraArgument: { recipeService, authService, userService, thunkErrorWrapper }, }, }), }); @@ -37,4 +40,13 @@ export type AppThunk = ThunkAction< unknown, Action >; + +export const createAppAsyncThunk = createAsyncThunk.withTypes<{ + state: RootState + dispatch: AppDispatch + rejectValue: string + extra: { recipeService: RecipeService, authService: AuthService, userService: UserService, thunkErrorWrapper: any } +}>(); export default store; + + From 8d3f458089589809f4e10378e7918e716d077571 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 03:24:52 +0300 Subject: [PATCH 20/73] refactor: added types to thunk actions --- .../app/actions/account/addFavoriteRecipe.ts | 34 ++++++++------ .../actions/account/deleteFavoriteRecipe.ts | 34 ++++++++------ .../actions/account/loadFavoriteRecipes.ts | 34 ++++++++------ .../src/app/actions/account/loginUser.ts | 30 +++++++----- .../src/app/actions/account/registerUser.ts | 29 +++++++----- .../src/app/actions/recipes/loadRecipes.ts | 46 ++++++++----------- 6 files changed, 111 insertions(+), 96 deletions(-) diff --git a/src/client/src/app/actions/account/addFavoriteRecipe.ts b/src/client/src/app/actions/account/addFavoriteRecipe.ts index ebc91f1..b15c8db 100644 --- a/src/client/src/app/actions/account/addFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/addFavoriteRecipe.ts @@ -1,16 +1,20 @@ -import { createAsyncThunk } from '@reduxjs/toolkit'; +import { createAppAsyncThunk } from '../../store'; +import { Recipe } from '../../../services/models/Recipe'; +import { AuthError } from '../../slices/types/Auth/AuthState'; -export const addFavoriteRecipe = createAsyncThunk( - 'account/addFavoriteRecipe', - async ({ recipe }, thunkAPI) => { - if (!thunkAPI.extra.userService.token) { - thunkAPI.extra.userService.setToken(thunkAPI.getState().account.token); - } - const thunk = thunkAPI.extra.thunkErrorWrapper( - thunkAPI.extra.userService.addFavoriteRecipe, - thunkAPI.rejectWithValue, - thunkAPI.extra.userService - ); - await thunk(recipe); - }, -); +export const addFavoriteRecipe = createAppAsyncThunk( + 'account/addFavoriteRecipe', + async (recipe: Recipe, thunkAPI) => { + if (!thunkAPI.extra.userService.token) { + thunkAPI.extra.userService.setToken(thunkAPI.getState().account.token); + } + const thunk = thunkAPI.extra.thunkErrorWrapper( + thunkAPI.extra.userService.addFavoriteRecipe, + thunkAPI.rejectWithValue, + thunkAPI.extra.userService + ); + return await thunk(recipe); + }, + ); diff --git a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts index d5748df..b2c0cf0 100644 --- a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts @@ -1,16 +1,20 @@ -import { createAsyncThunk } from '@reduxjs/toolkit'; +import { Recipe } from '../../../services/models/Recipe'; +import { AuthError } from '../../slices/types/Auth/AuthState'; +import { createAppAsyncThunk } from '../../store'; -export const deleteFavoriteRecipe = createAsyncThunk( - 'account/deleteFavoriteRecipe', - async ({ recipe }, thunkAPI) => { - if (!thunkAPI.extra.userService.token) { - thunkAPI.extra.userService.setToken(thunkAPI.getState().account.token); - } - const thunk = thunkAPI.extra.thunkErrorWrapper( - thunkAPI.extra.userService.deleteFavoriteRecipe, - thunkAPI.rejectWithValue, - thunkAPI.extra.userService - ); - await thunk(recipe); - }, -); +export const deleteFavoriteRecipe = createAppAsyncThunk( + 'account/deleteFavoriteRecipe', + async (recipe, thunkAPI) => { + if (!thunkAPI.extra.userService.token) { + thunkAPI.extra.userService.setToken(thunkAPI.getState().account.token); + } + const thunk = thunkAPI.extra.thunkErrorWrapper( + thunkAPI.extra.userService.deleteFavoriteRecipe, + thunkAPI.rejectWithValue, + thunkAPI.extra.userService + ); + return await thunk(recipe); + }, + ); diff --git a/src/client/src/app/actions/account/loadFavoriteRecipes.ts b/src/client/src/app/actions/account/loadFavoriteRecipes.ts index b03703d..84e147b 100644 --- a/src/client/src/app/actions/account/loadFavoriteRecipes.ts +++ b/src/client/src/app/actions/account/loadFavoriteRecipes.ts @@ -1,16 +1,20 @@ -import { createAsyncThunk } from '@reduxjs/toolkit'; +import { createAppAsyncThunk } from '../../store'; +import { Recipe } from '../../../services/models/Recipe'; +import { AuthError } from '../../slices/types/Auth/AuthState'; -export const loadFavoriteRecipes = createAsyncThunk( - 'account/loadUserFavorites', - async (_, thunkAPI) => { - if (!thunkAPI.extra.userService.token) { - thunkAPI.extra.userService.setToken(thunkAPI.getState().account.token); - } - const thunk = thunkAPI.extra.thunkErrorWrapper( - thunkAPI.extra.userService.getFavoriteRecipes, - thunkAPI.rejectWithValue, - thunkAPI.extra.userService - ); - await thunk(); - }, -); +export const loadFavoriteRecipes = createAppAsyncThunk( + 'account/loadUserFavorites', + async (_, thunkAPI) => { + if (!thunkAPI.extra.userService.token) { + thunkAPI.extra.userService.setToken(thunkAPI.getState().account.token); + } + const thunk = thunkAPI.extra.thunkErrorWrapper( + thunkAPI.extra.userService.getFavoriteRecipes, + thunkAPI.rejectWithValue, + thunkAPI.extra.userService + ); + return await thunk(); + }, + ); diff --git a/src/client/src/app/actions/account/loginUser.ts b/src/client/src/app/actions/account/loginUser.ts index e0817d7..f0b7bc8 100644 --- a/src/client/src/app/actions/account/loginUser.ts +++ b/src/client/src/app/actions/account/loginUser.ts @@ -1,13 +1,19 @@ -import { createAsyncThunk } from '@reduxjs/toolkit'; -export const loginUser = createAsyncThunk( - 'account/login', - async ({ credentials }, thunkAPI) => { - const thunk = thunkAPI.extra.thunkErrorWrapper( - thunkAPI.extra.authService.login, - thunkAPI.rejectWithValue, - thunkAPI.extra.authService - ); - await thunk(credentials); - } -); +import { createAppAsyncThunk } from '../../store'; +import { AuthError } from '../../slices/types/Auth/AuthState'; +import { AuthFulfilled } from '../../slices/types/Auth/AuthFulfilled'; +import { UserDTO } from '../../../services/DTO/UserDTO'; + +export const loginUser = createAppAsyncThunk( + 'account/login', + async (credentials: UserDTO, thunkAPI) => { + const thunk = thunkAPI.extra.thunkErrorWrapper( + thunkAPI.extra.authService.login, + thunkAPI.rejectWithValue, + thunkAPI.extra.authService + ); + return await thunk(credentials); + } + ); diff --git a/src/client/src/app/actions/account/registerUser.ts b/src/client/src/app/actions/account/registerUser.ts index 15f7a62..a453470 100644 --- a/src/client/src/app/actions/account/registerUser.ts +++ b/src/client/src/app/actions/account/registerUser.ts @@ -1,13 +1,18 @@ -import { createAsyncThunk } from '@reduxjs/toolkit'; +import { createAppAsyncThunk } from '../../store'; +import { AuthFulfilled } from '../../slices/types/Auth/AuthFulfilled'; +import { UserDTO } from '../../../services/DTO/UserDTO'; +import { AuthError } from '../../slices/types/Auth/AuthState'; -export const registerUser = createAsyncThunk( - 'account/register', - async ({ credentials }, thunkAPI) => { - const thunk = thunkAPI.extra.thunkErrorWrapper( - thunkAPI.extra.authService.register, - thunkAPI.rejectWithValue, - thunkAPI.extra.authService - ); - await thunk(credentials); - }, -); +export const registerUser = createAppAsyncThunk( + 'account/register', + async (credentials: UserDTO, thunkAPI) => { + const thunk = thunkAPI.extra.thunkErrorWrapper( + thunkAPI.extra.authService.register, + thunkAPI.rejectWithValue, + thunkAPI.extra.authService + ); + return await thunk(credentials); + } + ); diff --git a/src/client/src/app/actions/recipes/loadRecipes.ts b/src/client/src/app/actions/recipes/loadRecipes.ts index 27bf016..08b27de 100644 --- a/src/client/src/app/actions/recipes/loadRecipes.ts +++ b/src/client/src/app/actions/recipes/loadRecipes.ts @@ -1,29 +1,21 @@ -import { createAsyncThunk } from '@reduxjs/toolkit'; +import { Recipe } from '../../../services/models/Recipe'; +import { createAppAsyncThunk } from '../../store'; +import { RecipeError } from '../../slices/types/Recipe/RecipeState'; -export const loadRecipes = createAsyncThunk( - 'recipes/loadRecipes', - async ({ queryString }, { getState, rejectWithValue }) => { - const token = getState()?.account.token; - const headers = { - 'Content-Type': 'application/json', - 'authorization': token, - }; - const params = new URLSearchParams({ recipeName: queryString }); - try { - const response = await fetch('/recipes?' + params, { - method: 'GET', - headers, - }); - console.log(await response.json()); - if (!response.ok) { - return rejectWithValue(await response.json()); +export const loadRecipes = createAppAsyncThunk( + 'recipes/loadRecipes', + async (queryString: string, thunkAPI) => { + if (!thunkAPI.extra.recipeService.token) { + thunkAPI.extra.recipeService.setToken(thunkAPI.getState().account.token); } - return { - ...await response.json(), - }; - } catch (error) { - return rejectWithValue(error.response.data.message ?? error.message); - } - - }, -); + const thunk = thunkAPI.extra.thunkErrorWrapper( + thunkAPI.extra.recipeService.getRecipesByName, + thunkAPI.rejectWithValue, + thunkAPI.extra.recipeService + ); + const params = new URLSearchParams({ recipeName: queryString }); + return await thunk(params); + }, + ); From d0bb87d1655b9b5567a805e50629fa79a1857a6d Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 03:25:11 +0300 Subject: [PATCH 21/73] feat: typed accountSlice --- src/client/src/app/slices/accountSlice.ts | 52 ++++++++++++----------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/client/src/app/slices/accountSlice.ts b/src/client/src/app/slices/accountSlice.ts index a8c002c..2c19a77 100644 --- a/src/client/src/app/slices/accountSlice.ts +++ b/src/client/src/app/slices/accountSlice.ts @@ -1,31 +1,41 @@ -import { createSlice } from '@reduxjs/toolkit'; +import { Action, createSlice, PayloadAction } from '@reduxjs/toolkit'; import { loginUser } from '../actions/account/loginUser'; import { registerUser } from '../actions/account/registerUser'; import { loadFavoriteRecipes } from '../actions/account/loadFavoriteRecipes'; import { addFavoriteRecipe } from '../actions/account/addFavoriteRecipe'; import { deleteFavoriteRecipe } from '../actions/account/deleteFavoriteRecipe'; +import { AuthState } from './types/Auth/AuthState'; +import { AuthFulfilled } from './types/Auth/AuthFulfilled'; -const initialState = { - user: JSON.parse(localStorage.getItem('cyberChefUser')), - token: localStorage.getItem('cyberChefToken'), +const storageNames = { + user: 'cyberChefUser', + token: 'cyberChefToken', +}; + +const initialState: AuthState = { + user: JSON.parse(localStorage.getItem(storageNames.user) ?? ''), + token: localStorage.getItem(storageNames.token), userRecipes: [], loading: false, error: null, }; -const storageNames = { - user: 'cyberChefUser', - token: 'cyberChefToken', -}; +const isRejectedAction = (action: Action) => action.type.endsWith('rejected'); +const isPendingAction = (action: Action) => action.type.endsWith('pending'); -const isRejectedAction = action => action.type.endsWith('rejected'); -const isPendingAction = action => action.type.endsWith('pending'); +const saveUser = (state: AuthState, action: PayloadAction) => { + state.loading = false; + state.user = action.payload.user; + state.token = action.payload.accessToken; + localStorage.setItem(storageNames.user, JSON.stringify(state.user)); + localStorage.setItem(storageNames.token, state.token as string); +}; const accountSlice = createSlice({ name: 'account', initialState, reducers: { - logout(state) { + logout(state: AuthState) { state.user = null; state.token = null; localStorage.removeItem(storageNames.user); @@ -34,26 +44,18 @@ const accountSlice = createSlice({ }, extraReducers: builder => { builder.addCase(loginUser.fulfilled, (state, action) => { - state.loading = false; - state.user = action.payload.user; - state.token = action.payload.accessToken; - localStorage.setItem(storageNames.user, JSON.stringify(state.user)); - localStorage.setItem(storageNames.token, state.token); + saveUser(state, action); }); - builder.addCase(registerUser.fulfilled, (state, action) => { - state.loading = false; - state.user = action.payload.user; - state.token = action.payload.accessToken; - localStorage.setItem(storageNames.user, JSON.stringify(state.user)); - localStorage.setItem(storageNames.token, state.token); + builder.addCase(registerUser.fulfilled, (state: AuthState, action) => { + saveUser(state, action); }); - builder.addCase(loadFavoriteRecipes.fulfilled, (state, action) => { + builder.addCase(loadFavoriteRecipes.fulfilled, (state: AuthState, action) => { state.userRecipes = action.payload; }); - builder.addCase(addFavoriteRecipe.fulfilled, (state, action) => { + builder.addCase(addFavoriteRecipe.fulfilled, (state: AuthState, action) => { state.userRecipes.push(action.payload); }); - builder.addCase(deleteFavoriteRecipe.fulfilled, (state, action) => { + builder.addCase(deleteFavoriteRecipe.fulfilled, (state: AuthState, action) => { state.userRecipes = state.userRecipes.filter(item => item.id !== action.payload.id); }); builder.addMatcher(isRejectedAction, (state, action) => { From ea9c202415dc917b31b44b64ac2fdf0dcb0ad84c Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Tue, 6 Jun 2023 03:25:32 +0300 Subject: [PATCH 22/73] feat: typed recipesSlice --- src/client/src/app/slices/recipesSlice.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/client/src/app/slices/recipesSlice.ts b/src/client/src/app/slices/recipesSlice.ts index f51d90c..6157116 100644 --- a/src/client/src/app/slices/recipesSlice.ts +++ b/src/client/src/app/slices/recipesSlice.ts @@ -1,7 +1,8 @@ import { createSlice } from '@reduxjs/toolkit'; import { loadRecipes } from '../actions/recipes/loadRecipes'; +import { RecipeState } from './types/Recipe/RecipeState'; -const initialState = { +const initialState: RecipeState = { recipes: [], loading: false, error: null, From dd212893978272ae851cdf5271884cb65dfa8635 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 17:50:00 +0300 Subject: [PATCH 23/73] feat: typed UserService --- src/client/src/services/UserService.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/client/src/services/UserService.ts b/src/client/src/services/UserService.ts index cd0d1b4..6308b0c 100644 --- a/src/client/src/services/UserService.ts +++ b/src/client/src/services/UserService.ts @@ -1,39 +1,40 @@ import BaseService from './BaseService'; import UserError from './errors/UserError'; +import { Recipe } from './models/Recipe'; export default class UserService extends BaseService { - constructor(baseURL) { + constructor(baseURL: string) { super(baseURL); } - async getUserRecipes() { + async getUserRecipes(): Promise { try { return await this.request(`/user/authored`, 'GET'); } catch (error) { - throw new UserError('Error getting authored recipes: ' + error.message); + throw new UserError('Error getting authored recipes: ' + (error as Error).message); } } - async getFavoriteRecipes() { + async getFavoriteRecipes(): Promise { try { return await this.request(`/user`, 'GET'); } catch (error) { - throw new UserError('Error getting favorite recipes: ' + error.message); + throw new UserError('Error getting favorite recipes: ' + (error as Error).message); } } - async addFavoriteRecipe(userId, recipeId) { + async addFavoriteRecipe(userId: number, recipeId: number) { try { return await this.request(`/user`, 'POST', { userId, recipeId }); } catch (error) { - throw new UserError('Error adding favorite recipe: ' + error.message); + throw new UserError('Error adding favorite recipe: ' + (error as Error).message); } } - async deleteFavoriteRecipe(recipeId) { + async deleteFavoriteRecipe(recipeId: number) { try { return await this.request(`/user`, 'DELETE', recipeId); } catch (error) { - throw new UserError('Error deleting favorite recipe: ' + error.message); + throw new UserError('Error deleting favorite recipe: ' + (error as Error).message); } } From 8091b93b4bf52528138523064edccaa5e962124b Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 17:54:13 +0300 Subject: [PATCH 24/73] feat: RecipeDTO.ts for creating or updating recipes --- src/client/src/services/DTO/RecipeDTO.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/client/src/services/DTO/RecipeDTO.ts diff --git a/src/client/src/services/DTO/RecipeDTO.ts b/src/client/src/services/DTO/RecipeDTO.ts new file mode 100644 index 0000000..012584f --- /dev/null +++ b/src/client/src/services/DTO/RecipeDTO.ts @@ -0,0 +1,7 @@ +export interface RecipeDTO { + readonly name: string; + readonly categoryId: number; + readonly products?: string; + readonly description?: string; + readonly imageLink?: string; +} From 082ae197d79cd7879f1d0d5d4660a93a0e2996c1 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 17:54:26 +0300 Subject: [PATCH 25/73] feat: typed RecipeService.ts --- src/client/src/services/RecipeService.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/client/src/services/RecipeService.ts b/src/client/src/services/RecipeService.ts index 226697b..acebcd8 100644 --- a/src/client/src/services/RecipeService.ts +++ b/src/client/src/services/RecipeService.ts @@ -1,48 +1,50 @@ import BaseService from './BaseService'; import RecipeError from './errors/RecipeError'; +import { Recipe } from './models/Recipe'; +import { RecipeDTO } from './DTO/RecipeDTO'; export default class RecipeService extends BaseService { - constructor(baseURL) { + constructor(baseURL: string) { super(baseURL); } - async createRecipe(recipeData) { + async createRecipe(recipeData: RecipeDTO) { try { return await this.request(`/recipes`, 'POST', recipeData); } catch (error) { - throw new RecipeError('Error creating recipe: ' + error.message); + throw new RecipeError('Error creating recipe: ' + (error as Error).message); } } - async getRecipe(recipeId) { + async getRecipe(recipeId: number): Promise { try { return await this.request(`/recipes/${recipeId}`, 'GET'); } catch (error) { - throw new RecipeError('Error getting recipe: ' + error.message); + throw new RecipeError('Error getting recipe: ' + (error as Error).message); } } - async getRecipesByName(query) { + async getRecipesByName(query: string): Promise { try { return await this.request(`/recipes?${query}`, 'GET'); } catch (error) { - throw new RecipeError('Error getting recipes by name: ' + error.message); + throw new RecipeError('Error getting recipes by name: ' + (error as Error).message); } } - async updateRecipe(recipeId, recipeData) { + async updateRecipe(recipeId: number, recipeData: RecipeDTO) { try { return await this.request(`/recipes/${recipeId}`, 'PUT', recipeData); } catch (error) { - throw new RecipeError('Error updating recipe: ' + error.message); + throw new RecipeError('Error updating recipe: ' + (error as Error).message); } } - async deleteRecipe(recipeId) { + async deleteRecipe(recipeId: number) { try { return await this.request(`/recipes/${recipeId}`, 'DELETE'); } catch (error) { - throw new RecipeError('Error deleting recipe: ' + error.message); + throw new RecipeError('Error deleting recipe: ' + (error as Error).message); } } From 25da082f388eded1c9b647ea4bfedf56958f72d0 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 17:56:34 +0300 Subject: [PATCH 26/73] feat: typed AuthService.ts --- src/client/src/services/AuthService.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/client/src/services/AuthService.ts b/src/client/src/services/AuthService.ts index d6d8b0e..6ab190f 100644 --- a/src/client/src/services/AuthService.ts +++ b/src/client/src/services/AuthService.ts @@ -1,32 +1,30 @@ import BaseService from './BaseService'; import AuthError from './errors/AuthError'; +import { UserDTO } from './DTO/UserDTO'; +import { AuthFulfilled } from '../app/slices/types/Auth/AuthFulfilled'; export default class AuthService extends BaseService { - constructor(baseURL) { + constructor(baseURL: string) { super(baseURL); } - async register(userData) { + async register(userData: UserDTO): Promise { try { return await this.request('/register', 'POST', userData); } catch (error) { - throw new AuthError('Error registering: ' + error.message); + throw new AuthError('Error registering: ' + (error as Error).message); } } - async login(credentials) { + async login(username: string, password: string): Promise { try { - const response = await this.request('/login', 'POST', credentials); + const response = await this.request('/login', 'POST', { username, password }); if (response.token) { this.setToken(response.token); } return response; } catch (error) { - throw new AuthError('Error logging in: ' + error.message); + throw new AuthError('Error logging in: ' + (error as Error).message); } } - - async logout() { - this.setToken(null); - } } From 4761c10e6a01bccfd1ff24b21d3d4b49eb2c940f Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 17:57:36 +0300 Subject: [PATCH 27/73] refactor: added types to errors --- src/client/src/services/errors/AuthError.ts | 2 +- src/client/src/services/errors/BaseError.ts | 2 +- src/client/src/services/errors/RecipeError.ts | 2 +- src/client/src/services/errors/UserError.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client/src/services/errors/AuthError.ts b/src/client/src/services/errors/AuthError.ts index e4e65c6..5de2056 100644 --- a/src/client/src/services/errors/AuthError.ts +++ b/src/client/src/services/errors/AuthError.ts @@ -1,7 +1,7 @@ import BaseError from './BaseError'; export default class AuthError extends BaseError { - constructor(message) { + constructor(message: string) { super(message); } } diff --git a/src/client/src/services/errors/BaseError.ts b/src/client/src/services/errors/BaseError.ts index e61281b..b40508b 100644 --- a/src/client/src/services/errors/BaseError.ts +++ b/src/client/src/services/errors/BaseError.ts @@ -1,5 +1,5 @@ export default class BaseError extends Error { - constructor(message) { + constructor(message: string) { super(message); this.name = this.constructor.name; Error.captureStackTrace(this, this.constructor); diff --git a/src/client/src/services/errors/RecipeError.ts b/src/client/src/services/errors/RecipeError.ts index 5a70c8e..1d6746b 100644 --- a/src/client/src/services/errors/RecipeError.ts +++ b/src/client/src/services/errors/RecipeError.ts @@ -1,7 +1,7 @@ import BaseError from './BaseError'; export default class RecipeError extends BaseError { - constructor(message) { + constructor(message: string) { super(message); } } diff --git a/src/client/src/services/errors/UserError.ts b/src/client/src/services/errors/UserError.ts index fec4517..5d2a3d3 100644 --- a/src/client/src/services/errors/UserError.ts +++ b/src/client/src/services/errors/UserError.ts @@ -1,7 +1,7 @@ import BaseError from './BaseError'; export default class UserError extends BaseError { - constructor(message) { + constructor(message: string) { super(message); } } From c4704b1781f145ab08ab2548107148c369f09648 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:04:11 +0300 Subject: [PATCH 28/73] refactor: change prop types to ts way --- src/client/src/components/ErrorMessage.tsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/client/src/components/ErrorMessage.tsx b/src/client/src/components/ErrorMessage.tsx index dca725b..d510dfc 100644 --- a/src/client/src/components/ErrorMessage.tsx +++ b/src/client/src/components/ErrorMessage.tsx @@ -1,12 +1,11 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import React, { CSSProperties } from 'react'; -ErrorMessage.propTypes = { - error: PropTypes.object -}; +interface Props { + error: Error +} -function ErrorMessage({ error }) { - const styles = { +function ErrorMessage({ error }: Props) { + const styles: CSSProperties = { margin: '1rem', fontSize: '1.25rem', color: 'red', From d746b016ea112d5bf84c802f2c13cc83ce547439 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:04:24 +0300 Subject: [PATCH 29/73] refactor: type declarations --- src/client/src/setupProxy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/setupProxy.ts b/src/client/src/setupProxy.ts index 430c377..58795dd 100644 --- a/src/client/src/setupProxy.ts +++ b/src/client/src/setupProxy.ts @@ -3,7 +3,7 @@ const { createProxyMiddleware } = require('http-proxy-middleware'); import * as dotenv from 'dotenv'; dotenv.config(); -module.exports = function(app) { +module.exports = function(app: { use: (arg0: string, arg1: any) => void; }) { app.use( '/api', createProxyMiddleware({ From 8cf957f50c64099765999b968f24c591bafce4c8 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:04:57 +0300 Subject: [PATCH 30/73] refactor: fix to useAppSelector --- src/client/src/components/Header.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/src/components/Header.tsx b/src/client/src/components/Header.tsx index f6ded98..c006fe1 100644 --- a/src/client/src/components/Header.tsx +++ b/src/client/src/components/Header.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { Link } from 'react-router-dom'; -import { useSelector } from 'react-redux'; +import { useAppSelector } from '../app/store'; function Header() { - const user = useSelector(state => state.account.user); + const user = useAppSelector(state => state.account.user); return (
From c19372ed212df5fc90ddea60a4b329266e6ba230 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:08:38 +0300 Subject: [PATCH 31/73] feat: typed Recipe component --- src/client/src/components/Recipe.tsx | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/client/src/components/Recipe.tsx b/src/client/src/components/Recipe.tsx index 6ed2b5a..d42a459 100644 --- a/src/client/src/components/Recipe.tsx +++ b/src/client/src/components/Recipe.tsx @@ -1,19 +1,13 @@ import React from 'react'; -import PropTypes from 'prop-types'; +import { Recipe } from '../services/models/Recipe'; import { Link } from 'react-router-dom'; +interface Props { + recipe: Recipe, + clickHandler: (recipe: Recipe) => void, + deleteHandler: (recipe: Recipe) => void +} -Recipe.propTypes = { - recipe: PropTypes.shape({ - id: PropTypes.number, - name: PropTypes.string, - image_link: PropTypes.string, - products: PropTypes.string, - }), - clickHandler: PropTypes.func, - deleteHandler: PropTypes.func, -}; - -function Recipe({ recipe, clickHandler, deleteHandler }) { +function Recipe({ recipe, clickHandler, deleteHandler }: Props) { return (
From 66de8d4ab01d2948f8cf03278fa45aee1becbd4a Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:15:44 +0300 Subject: [PATCH 32/73] feat: typed Search component --- src/client/src/components/Search.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/client/src/components/Search.tsx b/src/client/src/components/Search.tsx index 2bca826..2158240 100644 --- a/src/client/src/components/Search.tsx +++ b/src/client/src/components/Search.tsx @@ -1,18 +1,18 @@ import React, { useState } from 'react'; -import PropTypes from 'prop-types'; -Search.propTypes = { - searchCallback: PropTypes.func, -}; +interface Props { + searchCallback: (event: React.FormEvent, formData: {queryString: string}) => void +} -function Search({ searchCallback }) { +function Search({ searchCallback } : Props) { const [formData, setFormData] = useState({ queryString: '', }); - const handleChange = e => { + const handleChange = (e: React.FormEvent) => { + const target = e.target as HTMLInputElement; setFormData({ ...formData, - [e.target.name]: e.target.value.trim(), + [target.name]: target.value.trim(), }); }; From ecab7f7ed0978c58911d4aada268334d58a406e4 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:16:47 +0300 Subject: [PATCH 33/73] refactor: fix file extension --- src/client/src/features/{AppRoutes.ts => AppRoutes.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/client/src/features/{AppRoutes.ts => AppRoutes.tsx} (100%) diff --git a/src/client/src/features/AppRoutes.ts b/src/client/src/features/AppRoutes.tsx similarity index 100% rename from src/client/src/features/AppRoutes.ts rename to src/client/src/features/AppRoutes.tsx From 0121f034f55ed7d8e73347c3ff3b66a1c96fca35 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:18:56 +0300 Subject: [PATCH 34/73] refactor: typed props ts way --- src/client/src/features/ProtectedRoute.tsx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/client/src/features/ProtectedRoute.tsx b/src/client/src/features/ProtectedRoute.tsx index adc16ee..f6aa169 100644 --- a/src/client/src/features/ProtectedRoute.tsx +++ b/src/client/src/features/ProtectedRoute.tsx @@ -1,20 +1,19 @@ import React from 'react'; import { Navigate } from 'react-router-dom'; -import PropTypes from 'prop-types'; +import { User } from '../services/models/User'; -const ProtectedRoute = ({ user, children }) => { +interface Props { + user: User, + children: React.FunctionComponent +} + + +const ProtectedRoute = ({ user, children }: Props) => { if (!user) { return ; } return children; }; -ProtectedRoute.propTypes = { - user: PropTypes.shape({ - userRecipes: PropTypes.array.isRequired, - username: PropTypes.string, - }), - children: PropTypes.element.isRequired, -}; export default ProtectedRoute; From b537da273ea58f48b65207b3f204ee0bab068f30 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:25:38 +0300 Subject: [PATCH 35/73] feat: typed class using enums --- src/client/src/features/ValidationError.ts | 29 ++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/client/src/features/ValidationError.ts b/src/client/src/features/ValidationError.ts index 43a15f5..f1266b5 100644 --- a/src/client/src/features/ValidationError.ts +++ b/src/client/src/features/ValidationError.ts @@ -1,24 +1,39 @@ +export const enum ValidationErrors { + Email = 'email', + Password = 'password', + Confirm = 'confirm', +} + +export const enum ValidationDescriptions { + Email = 'Invalid email', + PasswordShort = 'Password is shorter than 8 symbols', + PasswordEmpty = 'Password is required', + Confirm = 'Password does not match', +} + export default class ValidationError { - constructor(type, description) { + type: string; + description: string; + constructor(type: ValidationErrors, description: ValidationDescriptions) { this.type = type; this.description = description; } static defaultPasswordLength = 8; - static validate(data) { + static validate(data: { email: string; password: string; confirm?: string; }) { const emailRegex = /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/; const validationErrors = []; if (!emailRegex.test(data.email)) validationErrors.push(new ValidationError( - 'email', 'Invalid email', + ValidationErrors.Email, ValidationDescriptions.Email, )); if (data.password.length < ValidationError.defaultPasswordLength) validationErrors.push(new ValidationError( - 'password', 'Password is shorter than 8 symbols', - )); + ValidationErrors.Password, ValidationDescriptions.PasswordShort, + )); if (!data.password || !data.password.length) validationErrors.push(new ValidationError( - 'password', 'Password is required', + ValidationErrors.Password, ValidationDescriptions.PasswordEmpty, )); if (data.confirm && data.confirm !== data.password) validationErrors.push(new ValidationError( - 'confirm', 'Password does not match', + ValidationErrors.Confirm, ValidationDescriptions.Confirm, )); return validationErrors; } From aaedf44e99814195ce424c5a73ae717f8f9ad8d3 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:26:31 +0300 Subject: [PATCH 36/73] fix: changed useSelector to useAppSelector --- src/client/src/pages/Login.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/client/src/pages/Login.tsx b/src/client/src/pages/Login.tsx index 9b6f1bf..3f35643 100644 --- a/src/client/src/pages/Login.tsx +++ b/src/client/src/pages/Login.tsx @@ -4,9 +4,10 @@ import { useDispatch, useSelector } from 'react-redux'; import ValidationError from '../features/ValidationError'; import { loginUser } from '../app/actions/account/loginUser'; import ErrorMessage from '../components/ErrorMessage'; +import { useAppSelector } from '../app/store'; function Login() { - const { error, user } = useSelector(state => state.account); + const { error, user } = useAppSelector(state => state.account); const [formData, setFormData] = useState({ email: '', password: '', From fa409dc3680862495156fbb4e3885552c3c1f340 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:28:57 +0300 Subject: [PATCH 37/73] refactor: changed username to email --- src/client/src/services/DTO/UserDTO.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/services/DTO/UserDTO.ts b/src/client/src/services/DTO/UserDTO.ts index 4ee649b..412c88d 100644 --- a/src/client/src/services/DTO/UserDTO.ts +++ b/src/client/src/services/DTO/UserDTO.ts @@ -1,4 +1,4 @@ export interface UserDTO { - username: string, + email: string, password: string, } From 02449073888a03decbfe3398d7c943e913975843 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:32:34 +0300 Subject: [PATCH 38/73] refactor: fixed error type to Error --- src/client/src/app/slices/types/Auth/AuthState.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/app/slices/types/Auth/AuthState.ts b/src/client/src/app/slices/types/Auth/AuthState.ts index 0ce5bd6..3be1858 100644 --- a/src/client/src/app/slices/types/Auth/AuthState.ts +++ b/src/client/src/app/slices/types/Auth/AuthState.ts @@ -1,7 +1,7 @@ import { User } from '../../../../services/models/User'; import { Recipe } from '../../../../services/models/Recipe'; -export type AuthError = string | Error | undefined | null; +export type AuthError = Error | undefined | null; export interface AuthState { user: User | null, token: string | null, From 9511d98bd72d19c318a07185bcaf38643dd58e49 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:32:57 +0300 Subject: [PATCH 39/73] feat: typed Login page --- src/client/src/pages/Login.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/client/src/pages/Login.tsx b/src/client/src/pages/Login.tsx index 3f35643..59c073a 100644 --- a/src/client/src/pages/Login.tsx +++ b/src/client/src/pages/Login.tsx @@ -1,10 +1,9 @@ import React, { useEffect, useState } from 'react'; import { Link, useNavigate } from 'react-router-dom'; -import { useDispatch, useSelector } from 'react-redux'; import ValidationError from '../features/ValidationError'; import { loginUser } from '../app/actions/account/loginUser'; import ErrorMessage from '../components/ErrorMessage'; -import { useAppSelector } from '../app/store'; +import { useAppDispatch, useAppSelector } from '../app/store'; function Login() { const { error, user } = useAppSelector(state => state.account); @@ -12,17 +11,18 @@ function Login() { email: '', password: '', }); - const [errors, setErrors] = useState([]); + const [errors, setErrors] = useState([]); const navigate = useNavigate(); - const dispatch = useDispatch(); - const handleChange = e => { + const dispatch = useAppDispatch(); + const handleChange = (event: React.FormEvent) => { + const target = event.target as HTMLInputElement; setFormData({ ...formData, - [e.target.name]: e.target.value.trim(), + [target.name]: target.value.trim(), }); }; - const handleSubmit = event => { + const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); setErrors([]); const validationErrors = ValidationError.validate(formData); @@ -45,7 +45,7 @@ function Login() {

Login

- { error && } + { error && }

Date: Wed, 7 Jun 2023 18:38:03 +0300 Subject: [PATCH 40/73] refactor: changed Recipe model to RecipeModel.ts --- src/client/src/app/actions/account/addFavoriteRecipe.ts | 8 ++++---- .../src/app/actions/account/deleteFavoriteRecipe.ts | 6 +++--- src/client/src/app/actions/account/loadFavoriteRecipes.ts | 4 ++-- src/client/src/app/actions/recipes/loadRecipes.ts | 4 ++-- src/client/src/app/slices/types/Auth/AuthState.ts | 4 ++-- src/client/src/app/slices/types/Recipe/RecipeState.ts | 4 ++-- src/client/src/components/Recipe.tsx | 8 ++++---- src/client/src/services/RecipeService.ts | 6 +++--- src/client/src/services/UserService.ts | 6 +++--- .../src/services/models/{Recipe.ts => RecipeModel.ts} | 4 +--- 10 files changed, 26 insertions(+), 28 deletions(-) rename src/client/src/services/models/{Recipe.ts => RecipeModel.ts} (70%) diff --git a/src/client/src/app/actions/account/addFavoriteRecipe.ts b/src/client/src/app/actions/account/addFavoriteRecipe.ts index b15c8db..d875835 100644 --- a/src/client/src/app/actions/account/addFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/addFavoriteRecipe.ts @@ -1,12 +1,12 @@ import { createAppAsyncThunk } from '../../store'; -import { Recipe } from '../../../services/models/Recipe'; +import { RecipeModel } from '../../../services/models/RecipeModel'; import { AuthError } from '../../slices/types/Auth/AuthState'; -export const addFavoriteRecipe = createAppAsyncThunk( 'account/addFavoriteRecipe', - async (recipe: Recipe, thunkAPI) => { + async (recipe: RecipeModel, thunkAPI) => { if (!thunkAPI.extra.userService.token) { thunkAPI.extra.userService.setToken(thunkAPI.getState().account.token); } diff --git a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts index b2c0cf0..c1fec8c 100644 --- a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts @@ -1,9 +1,9 @@ -import { Recipe } from '../../../services/models/Recipe'; +import { RecipeModel } from '../../../services/models/RecipeModel'; import { AuthError } from '../../slices/types/Auth/AuthState'; import { createAppAsyncThunk } from '../../store'; -export const deleteFavoriteRecipe = createAppAsyncThunk( 'account/deleteFavoriteRecipe', async (recipe, thunkAPI) => { diff --git a/src/client/src/app/actions/account/loadFavoriteRecipes.ts b/src/client/src/app/actions/account/loadFavoriteRecipes.ts index 84e147b..7a4c89c 100644 --- a/src/client/src/app/actions/account/loadFavoriteRecipes.ts +++ b/src/client/src/app/actions/account/loadFavoriteRecipes.ts @@ -1,8 +1,8 @@ import { createAppAsyncThunk } from '../../store'; -import { Recipe } from '../../../services/models/Recipe'; +import { RecipeModel } from '../../../services/models/RecipeModel'; import { AuthError } from '../../slices/types/Auth/AuthState'; -export const loadFavoriteRecipes = createAppAsyncThunk( 'account/loadUserFavorites', diff --git a/src/client/src/app/actions/recipes/loadRecipes.ts b/src/client/src/app/actions/recipes/loadRecipes.ts index 08b27de..d6a1f3c 100644 --- a/src/client/src/app/actions/recipes/loadRecipes.ts +++ b/src/client/src/app/actions/recipes/loadRecipes.ts @@ -1,8 +1,8 @@ -import { Recipe } from '../../../services/models/Recipe'; +import { RecipeModel } from '../../../services/models/RecipeModel'; import { createAppAsyncThunk } from '../../store'; import { RecipeError } from '../../slices/types/Recipe/RecipeState'; -export const loadRecipes = createAppAsyncThunk( 'recipes/loadRecipes', diff --git a/src/client/src/app/slices/types/Auth/AuthState.ts b/src/client/src/app/slices/types/Auth/AuthState.ts index 3be1858..07db3a8 100644 --- a/src/client/src/app/slices/types/Auth/AuthState.ts +++ b/src/client/src/app/slices/types/Auth/AuthState.ts @@ -1,11 +1,11 @@ import { User } from '../../../../services/models/User'; -import { Recipe } from '../../../../services/models/Recipe'; +import { RecipeModel } from '../../../../services/models/RecipeModel'; export type AuthError = Error | undefined | null; export interface AuthState { user: User | null, token: string | null, - userRecipes: Recipe[], + userRecipes: RecipeModel[], loading: boolean, error: AuthError } diff --git a/src/client/src/app/slices/types/Recipe/RecipeState.ts b/src/client/src/app/slices/types/Recipe/RecipeState.ts index 203867d..287c109 100644 --- a/src/client/src/app/slices/types/Recipe/RecipeState.ts +++ b/src/client/src/app/slices/types/Recipe/RecipeState.ts @@ -1,8 +1,8 @@ -import { Recipe } from '../../../../services/models/Recipe'; +import { RecipeModel } from '../../../../services/models/RecipeModel'; export type RecipeError = string | Error | null | undefined; export interface RecipeState { - recipes: Recipe[], + recipes: RecipeModel[], loading: boolean, error: RecipeError } diff --git a/src/client/src/components/Recipe.tsx b/src/client/src/components/Recipe.tsx index d42a459..ba71da1 100644 --- a/src/client/src/components/Recipe.tsx +++ b/src/client/src/components/Recipe.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import { Recipe } from '../services/models/Recipe'; +import { RecipeModel } from '../services/models/RecipeModel'; import { Link } from 'react-router-dom'; interface Props { - recipe: Recipe, - clickHandler: (recipe: Recipe) => void, - deleteHandler: (recipe: Recipe) => void + recipe: RecipeModel, + clickHandler: (recipe: RecipeModel) => void, + deleteHandler: (recipe: RecipeModel) => void } function Recipe({ recipe, clickHandler, deleteHandler }: Props) { diff --git a/src/client/src/services/RecipeService.ts b/src/client/src/services/RecipeService.ts index acebcd8..e8644ea 100644 --- a/src/client/src/services/RecipeService.ts +++ b/src/client/src/services/RecipeService.ts @@ -1,6 +1,6 @@ import BaseService from './BaseService'; import RecipeError from './errors/RecipeError'; -import { Recipe } from './models/Recipe'; +import { RecipeModel } from './models/RecipeModel'; import { RecipeDTO } from './DTO/RecipeDTO'; export default class RecipeService extends BaseService { @@ -16,7 +16,7 @@ export default class RecipeService extends BaseService { } } - async getRecipe(recipeId: number): Promise { + async getRecipe(recipeId: number): Promise { try { return await this.request(`/recipes/${recipeId}`, 'GET'); } catch (error) { @@ -24,7 +24,7 @@ export default class RecipeService extends BaseService { } } - async getRecipesByName(query: string): Promise { + async getRecipesByName(query: string): Promise { try { return await this.request(`/recipes?${query}`, 'GET'); } catch (error) { diff --git a/src/client/src/services/UserService.ts b/src/client/src/services/UserService.ts index 6308b0c..ef27d33 100644 --- a/src/client/src/services/UserService.ts +++ b/src/client/src/services/UserService.ts @@ -1,13 +1,13 @@ import BaseService from './BaseService'; import UserError from './errors/UserError'; -import { Recipe } from './models/Recipe'; +import { RecipeModel } from './models/RecipeModel'; export default class UserService extends BaseService { constructor(baseURL: string) { super(baseURL); } - async getUserRecipes(): Promise { + async getUserRecipes(): Promise { try { return await this.request(`/user/authored`, 'GET'); } catch (error) { @@ -15,7 +15,7 @@ export default class UserService extends BaseService { } } - async getFavoriteRecipes(): Promise { + async getFavoriteRecipes(): Promise { try { return await this.request(`/user`, 'GET'); } catch (error) { diff --git a/src/client/src/services/models/Recipe.ts b/src/client/src/services/models/RecipeModel.ts similarity index 70% rename from src/client/src/services/models/Recipe.ts rename to src/client/src/services/models/RecipeModel.ts index e905a14..2d91eae 100644 --- a/src/client/src/services/models/Recipe.ts +++ b/src/client/src/services/models/RecipeModel.ts @@ -1,6 +1,4 @@ - - -export interface Recipe { +export interface RecipeModel { id: number, name: string, image_link: string, From f8b1a42b74bf3e2c8ae36a08ee70e7f55d6dcd6a Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:42:01 +0300 Subject: [PATCH 41/73] refactor: changed error names to avoid conflicts --- src/client/src/app/slices/types/Auth/AuthState.ts | 4 ++-- src/client/src/app/slices/types/Recipe/RecipeState.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client/src/app/slices/types/Auth/AuthState.ts b/src/client/src/app/slices/types/Auth/AuthState.ts index 07db3a8..9ac30f4 100644 --- a/src/client/src/app/slices/types/Auth/AuthState.ts +++ b/src/client/src/app/slices/types/Auth/AuthState.ts @@ -1,11 +1,11 @@ import { User } from '../../../../services/models/User'; import { RecipeModel } from '../../../../services/models/RecipeModel'; -export type AuthError = Error | undefined | null; +export type AuthStoreError = Error | undefined | null; export interface AuthState { user: User | null, token: string | null, userRecipes: RecipeModel[], loading: boolean, - error: AuthError + error: AuthStoreError } diff --git a/src/client/src/app/slices/types/Recipe/RecipeState.ts b/src/client/src/app/slices/types/Recipe/RecipeState.ts index 287c109..378b1eb 100644 --- a/src/client/src/app/slices/types/Recipe/RecipeState.ts +++ b/src/client/src/app/slices/types/Recipe/RecipeState.ts @@ -1,8 +1,8 @@ import { RecipeModel } from '../../../../services/models/RecipeModel'; -export type RecipeError = string | Error | null | undefined; +export type RecipeStoreError = Error | null | undefined; export interface RecipeState { recipes: RecipeModel[], loading: boolean, - error: RecipeError + error: RecipeStoreError } From 533e94bb7585283cf5c48421920023ab0558aaaf Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:52:12 +0300 Subject: [PATCH 42/73] fix: fixed props - callbacks are optional --- src/client/src/components/Recipe.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/src/components/Recipe.tsx b/src/client/src/components/Recipe.tsx index ba71da1..93aae30 100644 --- a/src/client/src/components/Recipe.tsx +++ b/src/client/src/components/Recipe.tsx @@ -3,8 +3,8 @@ import { RecipeModel } from '../services/models/RecipeModel'; import { Link } from 'react-router-dom'; interface Props { recipe: RecipeModel, - clickHandler: (recipe: RecipeModel) => void, - deleteHandler: (recipe: RecipeModel) => void + clickHandler?: (recipe: RecipeModel) => void, + deleteHandler?: (recipe: RecipeModel) => void } function Recipe({ recipe, clickHandler, deleteHandler }: Props) { From 9e091ed11656689c16e147dbb722cfe244cbf6ea Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:53:49 +0300 Subject: [PATCH 43/73] fix: fixed type annotations --- src/client/src/components/Search.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/components/Search.tsx b/src/client/src/components/Search.tsx index 2158240..bd0871a 100644 --- a/src/client/src/components/Search.tsx +++ b/src/client/src/components/Search.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; interface Props { - searchCallback: (event: React.FormEvent, formData: {queryString: string}) => void + searchCallback: (event: React.FormEvent, formData: { queryString: string }) => void } function Search({ searchCallback } : Props) { From 47f2c627d797bb259a347d68d5d7e17fb316b9e0 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:54:09 +0300 Subject: [PATCH 44/73] feat: typed SearchRecipes page --- src/client/src/pages/SearchRecipes.tsx | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/client/src/pages/SearchRecipes.tsx b/src/client/src/pages/SearchRecipes.tsx index 3e7c3aa..8d16f1b 100644 --- a/src/client/src/pages/SearchRecipes.tsx +++ b/src/client/src/pages/SearchRecipes.tsx @@ -1,23 +1,26 @@ import React, { useCallback, useEffect, useState } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; import Search from '../components/Search'; import { loadRecipes } from '../app/actions/recipes/loadRecipes'; import { addFavoriteRecipe } from '../app/actions/account/addFavoriteRecipe'; import Recipe from '../components/Recipe'; import Loader from '../components/Loader'; import ErrorMessage from '../components/ErrorMessage'; +import { useAppDispatch, useAppSelector } from '../app/store'; +import { RecipeModel } from '../services/models/RecipeModel'; function SearchRecipes() { - const [recipes, setRecipes] = useState([]); - const storeRecipes = useSelector(state => state.recipes.recipes); - const dispatch = useDispatch(); - const { error, loading } = useSelector(state => state.recipes.recipes); - const searchCallback = useCallback((event, { queryString }) => { - event.preventDefault(); - dispatch(loadRecipes(queryString)); - }, []); + const [recipes, setRecipes] = useState([]); + const { error, loading } = useAppSelector(state => state.recipes); + const storeRecipes = useAppSelector(state => state.recipes.recipes); + const dispatch = useAppDispatch(); + const searchCallback = useCallback( + (event: React.FormEvent, + { queryString }: { queryString: string }) => { + event.preventDefault(); + dispatch(loadRecipes(queryString)); + }, []); const clickCallback = useCallback( - recipe => dispatch(addFavoriteRecipe(recipe)), + (recipe: RecipeModel) => dispatch(addFavoriteRecipe(recipe)), [], ); @@ -37,7 +40,7 @@ function SearchRecipes() {
{recipes.map((recipe, index) => )} + key={index}/>)}
:

No recipes

}
From 243a4b23e341f6ca3ff93e57b9c241a7e1cb7339 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:56:04 +0300 Subject: [PATCH 45/73] feat: typed User page --- src/client/src/pages/User.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/client/src/pages/User.tsx b/src/client/src/pages/User.tsx index c719b80..6dea36d 100644 --- a/src/client/src/pages/User.tsx +++ b/src/client/src/pages/User.tsx @@ -1,23 +1,24 @@ import React, { useCallback, useEffect } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; import Recipe from '../components/Recipe'; import ErrorMessage from '../components/ErrorMessage'; import { loadFavoriteRecipes } from '../app/actions/account/loadFavoriteRecipes'; import Loader from '../components/Loader'; import { deleteFavoriteRecipe } from '../app/actions/account/deleteFavoriteRecipe'; +import { useAppDispatch, useAppSelector } from '../app/store'; +import { RecipeModel } from '../services/models/RecipeModel'; function User() { - const userRecipes = useSelector(state => state.account.userRecipes); - const { error, loading } = useSelector(state => state.account); - const dispatch = useDispatch(); - const deleteHandler = useCallback(recipe => { + const userRecipes = useAppSelector(state => state.account.userRecipes); + const { error, loading } = useAppSelector(state => state.account); + const dispatch = useAppDispatch(); + const deleteHandler = useCallback((recipe: RecipeModel) => { dispatch(deleteFavoriteRecipe(recipe)); }, [], ); useEffect(() => { - dispatch(loadFavoriteRecipes()); + dispatch(loadFavoriteRecipes(null)); }, []); if (loading) return ; From 93b30f3d0da08d9e9c8ee231b335246f6c597fbe Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:57:31 +0300 Subject: [PATCH 46/73] fix: fixed errors caused by type rename --- src/client/src/app/actions/account/addFavoriteRecipe.ts | 4 ++-- src/client/src/app/actions/account/deleteFavoriteRecipe.ts | 4 ++-- src/client/src/app/actions/account/loadFavoriteRecipes.ts | 4 ++-- src/client/src/app/actions/account/loginUser.ts | 4 ++-- src/client/src/app/actions/account/registerUser.ts | 4 ++-- src/client/src/app/actions/recipes/loadRecipes.ts | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/client/src/app/actions/account/addFavoriteRecipe.ts b/src/client/src/app/actions/account/addFavoriteRecipe.ts index d875835..433eee1 100644 --- a/src/client/src/app/actions/account/addFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/addFavoriteRecipe.ts @@ -1,10 +1,10 @@ import { createAppAsyncThunk } from '../../store'; import { RecipeModel } from '../../../services/models/RecipeModel'; -import { AuthError } from '../../slices/types/Auth/AuthState'; +import { AuthStoreError } from '../../slices/types/Auth/AuthState'; export const addFavoriteRecipe = createAppAsyncThunk( + { rejectValue: AuthStoreError }>( 'account/addFavoriteRecipe', async (recipe: RecipeModel, thunkAPI) => { if (!thunkAPI.extra.userService.token) { diff --git a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts index c1fec8c..e7e3420 100644 --- a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts @@ -1,10 +1,10 @@ import { RecipeModel } from '../../../services/models/RecipeModel'; -import { AuthError } from '../../slices/types/Auth/AuthState'; +import { AuthStoreError } from '../../slices/types/Auth/AuthState'; import { createAppAsyncThunk } from '../../store'; export const deleteFavoriteRecipe = createAppAsyncThunk( + { rejectValue: AuthStoreError }>( 'account/deleteFavoriteRecipe', async (recipe, thunkAPI) => { if (!thunkAPI.extra.userService.token) { diff --git a/src/client/src/app/actions/account/loadFavoriteRecipes.ts b/src/client/src/app/actions/account/loadFavoriteRecipes.ts index 7a4c89c..0e38f2e 100644 --- a/src/client/src/app/actions/account/loadFavoriteRecipes.ts +++ b/src/client/src/app/actions/account/loadFavoriteRecipes.ts @@ -1,10 +1,10 @@ import { createAppAsyncThunk } from '../../store'; import { RecipeModel } from '../../../services/models/RecipeModel'; -import { AuthError } from '../../slices/types/Auth/AuthState'; +import { AuthStoreError } from '../../slices/types/Auth/AuthState'; export const loadFavoriteRecipes = createAppAsyncThunk( + { rejectValue: AuthStoreError }>( 'account/loadUserFavorites', async (_, thunkAPI) => { if (!thunkAPI.extra.userService.token) { diff --git a/src/client/src/app/actions/account/loginUser.ts b/src/client/src/app/actions/account/loginUser.ts index f0b7bc8..4b17078 100644 --- a/src/client/src/app/actions/account/loginUser.ts +++ b/src/client/src/app/actions/account/loginUser.ts @@ -1,12 +1,12 @@ import { createAppAsyncThunk } from '../../store'; -import { AuthError } from '../../slices/types/Auth/AuthState'; +import { AuthStoreError } from '../../slices/types/Auth/AuthState'; import { AuthFulfilled } from '../../slices/types/Auth/AuthFulfilled'; import { UserDTO } from '../../../services/DTO/UserDTO'; export const loginUser = createAppAsyncThunk( + { rejectValue: AuthStoreError }>( 'account/login', async (credentials: UserDTO, thunkAPI) => { const thunk = thunkAPI.extra.thunkErrorWrapper( diff --git a/src/client/src/app/actions/account/registerUser.ts b/src/client/src/app/actions/account/registerUser.ts index a453470..278b93c 100644 --- a/src/client/src/app/actions/account/registerUser.ts +++ b/src/client/src/app/actions/account/registerUser.ts @@ -1,11 +1,11 @@ import { createAppAsyncThunk } from '../../store'; import { AuthFulfilled } from '../../slices/types/Auth/AuthFulfilled'; import { UserDTO } from '../../../services/DTO/UserDTO'; -import { AuthError } from '../../slices/types/Auth/AuthState'; +import { AuthStoreError } from '../../slices/types/Auth/AuthState'; export const registerUser = createAppAsyncThunk( + { rejectValue: AuthStoreError }>( 'account/register', async (credentials: UserDTO, thunkAPI) => { const thunk = thunkAPI.extra.thunkErrorWrapper( diff --git a/src/client/src/app/actions/recipes/loadRecipes.ts b/src/client/src/app/actions/recipes/loadRecipes.ts index d6a1f3c..b117177 100644 --- a/src/client/src/app/actions/recipes/loadRecipes.ts +++ b/src/client/src/app/actions/recipes/loadRecipes.ts @@ -1,10 +1,10 @@ import { RecipeModel } from '../../../services/models/RecipeModel'; import { createAppAsyncThunk } from '../../store'; -import { RecipeError } from '../../slices/types/Recipe/RecipeState'; +import { RecipeStoreError } from '../../slices/types/Recipe/RecipeState'; export const loadRecipes = createAppAsyncThunk( + { rejectValue: RecipeStoreError }>( 'recipes/loadRecipes', async (queryString: string, thunkAPI) => { if (!thunkAPI.extra.recipeService.token) { From 86353920bc94ca23dd294cba537fd2912822d2c5 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:58:49 +0300 Subject: [PATCH 47/73] fix: fixed type for User --- src/client/src/features/ProtectedRoute.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/features/ProtectedRoute.tsx b/src/client/src/features/ProtectedRoute.tsx index f6aa169..115e434 100644 --- a/src/client/src/features/ProtectedRoute.tsx +++ b/src/client/src/features/ProtectedRoute.tsx @@ -3,7 +3,7 @@ import { Navigate } from 'react-router-dom'; import { User } from '../services/models/User'; interface Props { - user: User, + user: User | null, children: React.FunctionComponent } From c51e763adfad664da60d96e9e1b4484e9ab57392 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:03:12 +0300 Subject: [PATCH 48/73] fix: fixed type for children prop --- src/client/src/features/ProtectedRoute.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/src/features/ProtectedRoute.tsx b/src/client/src/features/ProtectedRoute.tsx index 115e434..d80b9b7 100644 --- a/src/client/src/features/ProtectedRoute.tsx +++ b/src/client/src/features/ProtectedRoute.tsx @@ -4,7 +4,7 @@ import { User } from '../services/models/User'; interface Props { user: User | null, - children: React.FunctionComponent + children: React.FunctionComponent | React.JSX.Element } @@ -12,7 +12,7 @@ const ProtectedRoute = ({ user, children }: Props) => { if (!user) { return ; } - return children; + return <>{children}; }; From 9812564821fd7e94dff68e217dd45a0609005141 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:03:25 +0300 Subject: [PATCH 49/73] feat: typed main component --- src/client/src/App.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client/src/App.tsx b/src/client/src/App.tsx index 9d78445..7833aba 100644 --- a/src/client/src/App.tsx +++ b/src/client/src/App.tsx @@ -4,11 +4,11 @@ import { AppRoutes, ProtectedAppRoutes } from './features/AppRoutes'; import Header from './components/Header'; import Footer from './components/Footer'; import ProtectedRoute from './features/ProtectedRoute'; -import { useSelector } from 'react-redux'; import ErrorMessage from './components/ErrorMessage'; +import { useAppSelector } from './app/store'; function App() { - const user = useSelector(state => state.account.user) || null; + const user = useAppSelector(state => state.account.user) || null; return (
@@ -25,7 +25,7 @@ function App() { {element} } />; })} - } /> + } />
From 99c8c53385a73a1551cd22addfc1b63af1476a05 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:08:10 +0300 Subject: [PATCH 50/73] chore: installed dotenv --- src/client/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/client/package.json b/src/client/package.json index 1aa0afd..d6687ae 100644 --- a/src/client/package.json +++ b/src/client/package.json @@ -11,6 +11,7 @@ "@types/node": "^20.2.5", "@types/react": "^18.2.8", "@types/react-dom": "^18.2.4", + "dotenv": "^16.1.4", "http-proxy-middleware": "^2.0.6", "prop-types": "^15.8.1", "react": "^18.2.0", From b87213299c69b98e099acf63b9e75ec0e75164a0 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:08:48 +0300 Subject: [PATCH 51/73] fix: fixed base url type --- src/client/src/app/store.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/client/src/app/store.ts b/src/client/src/app/store.ts index 313fd4f..4c6b736 100644 --- a/src/client/src/app/store.ts +++ b/src/client/src/app/store.ts @@ -7,9 +7,11 @@ import { thunkErrorWrapper } from './utils/thunkErrorWrapper'; import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; import UserService from '../services/UserService'; -const recipeService = new RecipeService(process.env.BASE_URL); -const authService = new AuthService(process.env.BASE_URL); -const userService = new UserService(process.env.BASE_URL); +const baseURL = process.env.BASE_URL || 'http://localhost:3000/'; + +const recipeService = new RecipeService(baseURL); +const authService = new AuthService(baseURL); +const userService = new UserService(baseURL); const rootReducer = combineReducers({ From 0b34fc2ec73c27cc92b80b4d112199527f5fc303 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:09:07 +0300 Subject: [PATCH 52/73] feat: added dotenv config in index --- src/client/src/index.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/client/src/index.tsx b/src/client/src/index.tsx index baf0c4a..06815ad 100644 --- a/src/client/src/index.tsx +++ b/src/client/src/index.tsx @@ -6,6 +6,9 @@ import App from './App'; import reportWebVitals from './reportWebVitals'; import './index.css'; import { BrowserRouter } from 'react-router-dom'; +import dotenv from 'dotenv'; + +dotenv.config(); const container = document.getElementById('root') as HTMLElement; const root = createRoot(container); From 77351bcaa2de1b1029665306d9e12d98c583f44d Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:24:34 +0300 Subject: [PATCH 53/73] fix: fixed redux circular import --- .../src/app/actions/account/addFavoriteRecipe.ts | 2 +- .../src/app/actions/account/deleteFavoriteRecipe.ts | 2 +- .../src/app/actions/account/loadFavoriteRecipes.ts | 2 +- src/client/src/app/actions/account/loginUser.ts | 3 +-- src/client/src/app/actions/account/registerUser.ts | 2 +- src/client/src/app/actions/recipes/loadRecipes.ts | 2 +- src/client/src/app/store.ts | 10 ++-------- src/client/src/app/utils/createAppAsync.ts | 12 ++++++++++++ 8 files changed, 20 insertions(+), 15 deletions(-) create mode 100644 src/client/src/app/utils/createAppAsync.ts diff --git a/src/client/src/app/actions/account/addFavoriteRecipe.ts b/src/client/src/app/actions/account/addFavoriteRecipe.ts index 433eee1..5a9c79c 100644 --- a/src/client/src/app/actions/account/addFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/addFavoriteRecipe.ts @@ -1,4 +1,4 @@ -import { createAppAsyncThunk } from '../../store'; +import { createAppAsyncThunk } from '../../utils/createAppAsync'; import { RecipeModel } from '../../../services/models/RecipeModel'; import { AuthStoreError } from '../../slices/types/Auth/AuthState'; diff --git a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts index e7e3420..981b923 100644 --- a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts @@ -1,6 +1,6 @@ import { RecipeModel } from '../../../services/models/RecipeModel'; import { AuthStoreError } from '../../slices/types/Auth/AuthState'; -import { createAppAsyncThunk } from '../../store'; +import { createAppAsyncThunk } from '../../utils/createAppAsync'; export const deleteFavoriteRecipe = createAppAsyncThunk; export const useAppDispatch: () => AppDispatch = useDispatch; @@ -43,12 +42,7 @@ export type AppThunk = ThunkAction< Action >; -export const createAppAsyncThunk = createAsyncThunk.withTypes<{ - state: RootState - dispatch: AppDispatch - rejectValue: string - extra: { recipeService: RecipeService, authService: AuthService, userService: UserService, thunkErrorWrapper: any } -}>(); +export { store, recipeService, authService, userService }; export default store; diff --git a/src/client/src/app/utils/createAppAsync.ts b/src/client/src/app/utils/createAppAsync.ts new file mode 100644 index 0000000..9dd9d65 --- /dev/null +++ b/src/client/src/app/utils/createAppAsync.ts @@ -0,0 +1,12 @@ +import { createAsyncThunk } from '@reduxjs/toolkit'; +import RecipeService from '../../services/RecipeService'; +import AuthService from '../../services/AuthService'; +import UserService from '../../services/UserService'; +import { AppDispatch, RootState } from '../store'; + +export const createAppAsyncThunk = createAsyncThunk.withTypes<{ + state: RootState, + dispatch: AppDispatch, + rejectValue: string, + extra: { recipeService: RecipeService, authService: AuthService, userService: UserService, thunkErrorWrapper: any } +}>(); From b05eb79ba66f66324875b2c97631c0d4d9c75030 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:24:52 +0300 Subject: [PATCH 54/73] fix: delete unnecessary dotenv --- src/client/src/index.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/client/src/index.tsx b/src/client/src/index.tsx index 06815ad..baf0c4a 100644 --- a/src/client/src/index.tsx +++ b/src/client/src/index.tsx @@ -6,9 +6,6 @@ import App from './App'; import reportWebVitals from './reportWebVitals'; import './index.css'; import { BrowserRouter } from 'react-router-dom'; -import dotenv from 'dotenv'; - -dotenv.config(); const container = document.getElementById('root') as HTMLElement; const root = createRoot(container); From 6cab82c50aac6a3810b4931f94483d87afb860db Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:26:50 +0300 Subject: [PATCH 55/73] chore: delete dotenv --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 0815d7d..0a290af 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,6 @@ "cheerio": "^1.0.0-rc.10", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", - "dotenv": "^10.0.0", "express": "^4.17.2", "express-validator": "^6.14.0", "jsonwebtoken": "^9.0.0", @@ -32,7 +31,7 @@ }, "scripts": { "installDependecies": "npm install && npm install --prefix src/client", - "start":" npm run --prefix src/client build && nest start", + "start": " npm run --prefix src/client build && nest start", "start:dev": "nest start --watch" }, "devDependencies": { From 1391c56c25ed84546d22e3118f7933ed078618d6 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:30:56 +0300 Subject: [PATCH 56/73] fix: fixed json error --- src/client/src/app/slices/accountSlice.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/app/slices/accountSlice.ts b/src/client/src/app/slices/accountSlice.ts index 2c19a77..0e6acf1 100644 --- a/src/client/src/app/slices/accountSlice.ts +++ b/src/client/src/app/slices/accountSlice.ts @@ -13,7 +13,7 @@ const storageNames = { }; const initialState: AuthState = { - user: JSON.parse(localStorage.getItem(storageNames.user) ?? ''), + user: JSON.parse(localStorage.getItem(storageNames.user) ?? 'null'), token: localStorage.getItem(storageNames.token), userRecipes: [], loading: false, From 80d038ab9dfa8f7ab83ad4f8704a7c5215752df5 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:34:32 +0300 Subject: [PATCH 57/73] chore: deleted prop-types --- src/client/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/package.json b/src/client/package.json index d6687ae..36a70f3 100644 --- a/src/client/package.json +++ b/src/client/package.json @@ -13,7 +13,6 @@ "@types/react-dom": "^18.2.4", "dotenv": "^16.1.4", "http-proxy-middleware": "^2.0.6", - "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-redux": "^8.0.5", From 55fa47dfc8ef609a128f119736ee303d5ee7da31 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:35:07 +0300 Subject: [PATCH 58/73] chore: returned dotenv to main package --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 0a290af..c48722f 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "cheerio": "^1.0.0-rc.10", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", + "dotenv": "^16.1.4", "express": "^4.17.2", "express-validator": "^6.14.0", "jsonwebtoken": "^9.0.0", From bd85258445536e968741c382a6a6d2e3704c8f72 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Wed, 7 Jun 2023 19:36:00 +0300 Subject: [PATCH 59/73] chore: deleted dotenv from client --- src/client/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/package.json b/src/client/package.json index 36a70f3..c443ce9 100644 --- a/src/client/package.json +++ b/src/client/package.json @@ -11,7 +11,6 @@ "@types/node": "^20.2.5", "@types/react": "^18.2.8", "@types/react-dom": "^18.2.4", - "dotenv": "^16.1.4", "http-proxy-middleware": "^2.0.6", "react": "^18.2.0", "react-dom": "^18.2.0", From bd2282711310251fca2ea5f20981a99ae896e08e Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 19:41:25 +0300 Subject: [PATCH 60/73] refactor: typed thunkWrapper using generics --- src/client/src/app/utils/thunkErrorWrapper.ts | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/client/src/app/utils/thunkErrorWrapper.ts b/src/client/src/app/utils/thunkErrorWrapper.ts index bc76514..14ee90c 100644 --- a/src/client/src/app/utils/thunkErrorWrapper.ts +++ b/src/client/src/app/utils/thunkErrorWrapper.ts @@ -1,11 +1,17 @@ -export const thunkErrorWrapper = (method: any, rejectWithValue: any, context = null) => async (...args : any) => { - try { - const response = await method.apply(context, args); - if (response.error) { - return rejectWithValue(response.error); +import BaseService from '../../services/BaseService'; + +export function thunkErrorWrapper(method: (...args : Args[]) => ReturnType, + rejectWithValue: (error: string) => void, + context: BaseService | null = null) { + return async (...args : Args[]) => { + try { + const response = await method.apply(context, args); + if ((response as any).error) { + return rejectWithValue((response as any).error); + } + return response; + } catch (error: any) { + return rejectWithValue(error.response.data.message ?? error.message); } - return response; - } catch (error: any) { - return rejectWithValue(error.response.data.message ?? error.message); - } -}; + }; +} From 86c523908d98714526c3a4d10c21d1af13636ff7 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 20:13:09 +0300 Subject: [PATCH 61/73] refactor: rename createAppAsyncThunk.ts --- .../src/app/utils/{createAppAsync.ts => createAppAsyncThunk.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/client/src/app/utils/{createAppAsync.ts => createAppAsyncThunk.ts} (100%) diff --git a/src/client/src/app/utils/createAppAsync.ts b/src/client/src/app/utils/createAppAsyncThunk.ts similarity index 100% rename from src/client/src/app/utils/createAppAsync.ts rename to src/client/src/app/utils/createAppAsyncThunk.ts From 41607fa7a38134f525a747df65d6e850d686ff12 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 20:13:41 +0300 Subject: [PATCH 62/73] refactor: fix type annotation --- src/client/src/services/UserService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/src/services/UserService.ts b/src/client/src/services/UserService.ts index ef27d33..369a2e6 100644 --- a/src/client/src/services/UserService.ts +++ b/src/client/src/services/UserService.ts @@ -23,14 +23,14 @@ export default class UserService extends BaseService { } } - async addFavoriteRecipe(userId: number, recipeId: number) { + async addFavoriteRecipe(userId: number, recipeId: number): Promise { try { return await this.request(`/user`, 'POST', { userId, recipeId }); } catch (error) { throw new UserError('Error adding favorite recipe: ' + (error as Error).message); } } - async deleteFavoriteRecipe(recipeId: number) { + async deleteFavoriteRecipe(recipeId: number): Promise { try { return await this.request(`/user`, 'DELETE', recipeId); } catch (error) { From 1a07bee011ab920458865fef9609abd1d8e592b9 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 20:14:14 +0300 Subject: [PATCH 63/73] fix: fixed types in thunkErrorWrapper.ts --- src/client/src/app/utils/thunkErrorWrapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/app/utils/thunkErrorWrapper.ts b/src/client/src/app/utils/thunkErrorWrapper.ts index 14ee90c..5d7423c 100644 --- a/src/client/src/app/utils/thunkErrorWrapper.ts +++ b/src/client/src/app/utils/thunkErrorWrapper.ts @@ -1,7 +1,7 @@ import BaseService from '../../services/BaseService'; export function thunkErrorWrapper(method: (...args : Args[]) => ReturnType, - rejectWithValue: (error: string) => void, + rejectWithValue: (value: Error) => any, context: BaseService | null = null) { return async (...args : Args[]) => { try { From a4cf66e1e0f51350315c9e91d49dd8f1f7c286e9 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 20:15:03 +0300 Subject: [PATCH 64/73] refactor: delete unnecessary import --- src/client/src/app/store.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/client/src/app/store.ts b/src/client/src/app/store.ts index e3e8f26..24f8a38 100644 --- a/src/client/src/app/store.ts +++ b/src/client/src/app/store.ts @@ -1,9 +1,8 @@ -import { Action, combineReducers, configureStore, createAsyncThunk, ThunkAction } from '@reduxjs/toolkit'; +import { Action, combineReducers, configureStore, ThunkAction } from '@reduxjs/toolkit'; import accountReducer from './slices/accountSlice'; import recipesReducer from './slices/recipesSlice'; import AuthService from '../services/AuthService'; import RecipeService from '../services/RecipeService'; -import { thunkErrorWrapper } from './utils/thunkErrorWrapper'; import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; import UserService from '../services/UserService'; @@ -25,7 +24,7 @@ const store = configureStore({ middleware: getDefaultMiddleware => getDefaultMiddleware({ thunk: { - extraArgument: { recipeService, authService, userService, thunkErrorWrapper }, + extraArgument: { recipeService, authService, userService }, }, }), }); From ae9fb78bef96d1fd3102e8012011c40771146945 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 20:15:31 +0300 Subject: [PATCH 65/73] refactor: fix type annotation --- src/client/src/services/RecipeService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/services/RecipeService.ts b/src/client/src/services/RecipeService.ts index e8644ea..a5f530a 100644 --- a/src/client/src/services/RecipeService.ts +++ b/src/client/src/services/RecipeService.ts @@ -24,7 +24,7 @@ export default class RecipeService extends BaseService { } } - async getRecipesByName(query: string): Promise { + async getRecipesByName(query: URLSearchParams): Promise { try { return await this.request(`/recipes?${query}`, 'GET'); } catch (error) { From f47067ab8992adf0c7bafd563d93380034ec7fee Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 20:16:12 +0300 Subject: [PATCH 66/73] fix: fixed files using typed thunkWrapper --- .../src/app/actions/account/addFavoriteRecipe.ts | 15 ++++++++------- .../app/actions/account/deleteFavoriteRecipe.ts | 14 +++++++------- .../app/actions/account/loadFavoriteRecipes.ts | 5 +++-- src/client/src/app/actions/recipes/loadRecipes.ts | 5 +++-- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/client/src/app/actions/account/addFavoriteRecipe.ts b/src/client/src/app/actions/account/addFavoriteRecipe.ts index 5a9c79c..90f9d9c 100644 --- a/src/client/src/app/actions/account/addFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/addFavoriteRecipe.ts @@ -1,20 +1,21 @@ -import { createAppAsyncThunk } from '../../utils/createAppAsync'; -import { RecipeModel } from '../../../services/models/RecipeModel'; +import { createAppAsyncThunk } from '../../utils/createAppAsyncThunk'; import { AuthStoreError } from '../../slices/types/Auth/AuthState'; +import { thunkErrorWrapper } from '../../utils/thunkErrorWrapper'; -export const addFavoriteRecipe = createAppAsyncThunk, + { userId: number, recipeId: number }, { rejectValue: AuthStoreError }>( 'account/addFavoriteRecipe', - async (recipe: RecipeModel, thunkAPI) => { + async (ids: { userId: number, recipeId: number }, thunkAPI) => { if (!thunkAPI.extra.userService.token) { thunkAPI.extra.userService.setToken(thunkAPI.getState().account.token); } - const thunk = thunkAPI.extra.thunkErrorWrapper( + const { userId, recipeId } = ids; + const thunk = thunkErrorWrapper( thunkAPI.extra.userService.addFavoriteRecipe, thunkAPI.rejectWithValue, thunkAPI.extra.userService ); - return await thunk(recipe); + return await thunk(userId, recipeId); }, ); diff --git a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts index 981b923..22738c1 100644 --- a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts @@ -1,20 +1,20 @@ -import { RecipeModel } from '../../../services/models/RecipeModel'; import { AuthStoreError } from '../../slices/types/Auth/AuthState'; -import { createAppAsyncThunk } from '../../utils/createAppAsync'; +import { createAppAsyncThunk } from '../../utils/createAppAsyncThunk'; +import { thunkErrorWrapper } from '../../utils/thunkErrorWrapper'; -export const deleteFavoriteRecipe = createAppAsyncThunk( 'account/deleteFavoriteRecipe', - async (recipe, thunkAPI) => { + async ({ recipeId }, thunkAPI) => { if (!thunkAPI.extra.userService.token) { thunkAPI.extra.userService.setToken(thunkAPI.getState().account.token); } - const thunk = thunkAPI.extra.thunkErrorWrapper( + const thunk = thunkErrorWrapper( thunkAPI.extra.userService.deleteFavoriteRecipe, thunkAPI.rejectWithValue, thunkAPI.extra.userService ); - return await thunk(recipe); + return await thunk(recipeId); }, ); diff --git a/src/client/src/app/actions/account/loadFavoriteRecipes.ts b/src/client/src/app/actions/account/loadFavoriteRecipes.ts index 21e99f3..6819b94 100644 --- a/src/client/src/app/actions/account/loadFavoriteRecipes.ts +++ b/src/client/src/app/actions/account/loadFavoriteRecipes.ts @@ -1,6 +1,7 @@ -import { createAppAsyncThunk } from '../../utils/createAppAsync'; +import { createAppAsyncThunk } from '../../utils/createAppAsyncThunk'; import { RecipeModel } from '../../../services/models/RecipeModel'; import { AuthStoreError } from '../../slices/types/Auth/AuthState'; +import { thunkErrorWrapper } from '../../utils/thunkErrorWrapper'; export const loadFavoriteRecipes = createAppAsyncThunk Date: Fri, 9 Jun 2023 20:17:30 +0300 Subject: [PATCH 67/73] fix: added necessary fields to DTO --- src/client/src/services/DTO/UserDTO.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client/src/services/DTO/UserDTO.ts b/src/client/src/services/DTO/UserDTO.ts index 412c88d..ce457ef 100644 --- a/src/client/src/services/DTO/UserDTO.ts +++ b/src/client/src/services/DTO/UserDTO.ts @@ -1,4 +1,6 @@ export interface UserDTO { email: string, + username?: string, + imageLink?: string, password: string, } From ebfc559b299ba5c5f4fdd8174a0d01e2f59c3fe0 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 20:18:32 +0300 Subject: [PATCH 68/73] fix: added necessary fields to RecipeModel --- src/client/src/services/models/RecipeModel.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/client/src/services/models/RecipeModel.ts b/src/client/src/services/models/RecipeModel.ts index 2d91eae..d284cb2 100644 --- a/src/client/src/services/models/RecipeModel.ts +++ b/src/client/src/services/models/RecipeModel.ts @@ -1,6 +1,10 @@ export interface RecipeModel { id: number, + category_id: number, + creator_id: number, name: string, image_link: string, products: string, + description: string, + } From 0b2b3d0f3e7f34d28bcd0c39f86d965c0d2ed965 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 20:19:34 +0300 Subject: [PATCH 69/73] fix: added necessary fields to UserModel --- src/client/src/services/models/User.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/client/src/services/models/User.ts b/src/client/src/services/models/User.ts index 48dcde5..80bfb5a 100644 --- a/src/client/src/services/models/User.ts +++ b/src/client/src/services/models/User.ts @@ -1,4 +1,6 @@ export interface User { - id: number; - username: string; + id: number, + username: string, + email: string, + image_link: string, } From 417faea9e09c22fbc984424f6e19f117da7cdab8 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 20:20:23 +0300 Subject: [PATCH 70/73] fix: fixed file to use typed thunkWrapper --- src/client/src/app/actions/account/loginUser.ts | 9 +++++---- src/client/src/app/actions/account/registerUser.ts | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/client/src/app/actions/account/loginUser.ts b/src/client/src/app/actions/account/loginUser.ts index 67b2ae7..4e72d2b 100644 --- a/src/client/src/app/actions/account/loginUser.ts +++ b/src/client/src/app/actions/account/loginUser.ts @@ -1,18 +1,19 @@ -import { createAppAsyncThunk } from '../../utils/createAppAsync'; +import { createAppAsyncThunk } from '../../utils/createAppAsyncThunk'; import { AuthStoreError } from '../../slices/types/Auth/AuthState'; import { AuthFulfilled } from '../../slices/types/Auth/AuthFulfilled'; import { UserDTO } from '../../../services/DTO/UserDTO'; +import { thunkErrorWrapper } from '../../utils/thunkErrorWrapper'; export const loginUser = createAppAsyncThunk( 'account/login', - async (credentials: UserDTO, thunkAPI) => { - const thunk = thunkAPI.extra.thunkErrorWrapper( + async ({ email, password }: UserDTO, thunkAPI) => { + const thunk = thunkErrorWrapper( thunkAPI.extra.authService.login, thunkAPI.rejectWithValue, thunkAPI.extra.authService ); - return await thunk(credentials); + return await thunk(email, password); } ); diff --git a/src/client/src/app/actions/account/registerUser.ts b/src/client/src/app/actions/account/registerUser.ts index f82cc70..d9950fa 100644 --- a/src/client/src/app/actions/account/registerUser.ts +++ b/src/client/src/app/actions/account/registerUser.ts @@ -1,4 +1,4 @@ -import { createAppAsyncThunk } from '../../utils/createAppAsync'; +import { createAppAsyncThunk } from '../../utils/createAppAsyncThunk'; import { AuthFulfilled } from '../../slices/types/Auth/AuthFulfilled'; import { UserDTO } from '../../../services/DTO/UserDTO'; import { AuthStoreError } from '../../slices/types/Auth/AuthState'; @@ -7,12 +7,12 @@ export const registerUser = createAppAsyncThunk( 'account/register', - async (credentials: UserDTO, thunkAPI) => { + async ({ username, password }, thunkAPI) => { const thunk = thunkAPI.extra.thunkErrorWrapper( thunkAPI.extra.authService.register, thunkAPI.rejectWithValue, thunkAPI.extra.authService ); - return await thunk(credentials); + return await thunk(username, password); } ); From dcd52a3420e212534e464a5987fd31ef60bc5279 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 20:23:16 +0300 Subject: [PATCH 71/73] fix: fixed return types --- .../src/app/actions/account/addFavoriteRecipe.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/client/src/app/actions/account/addFavoriteRecipe.ts b/src/client/src/app/actions/account/addFavoriteRecipe.ts index 90f9d9c..8727d5e 100644 --- a/src/client/src/app/actions/account/addFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/addFavoriteRecipe.ts @@ -1,21 +1,22 @@ import { createAppAsyncThunk } from '../../utils/createAppAsyncThunk'; import { AuthStoreError } from '../../slices/types/Auth/AuthState'; import { thunkErrorWrapper } from '../../utils/thunkErrorWrapper'; +import { RecipeModel } from '../../../services/models/RecipeModel'; -export const addFavoriteRecipe = createAppAsyncThunk, - { userId: number, recipeId: number }, +export const addFavoriteRecipe = createAppAsyncThunk( 'account/addFavoriteRecipe', - async (ids: { userId: number, recipeId: number }, thunkAPI) => { + async ({ userId, recipe }, thunkAPI) => { if (!thunkAPI.extra.userService.token) { thunkAPI.extra.userService.setToken(thunkAPI.getState().account.token); } - const { userId, recipeId } = ids; const thunk = thunkErrorWrapper( thunkAPI.extra.userService.addFavoriteRecipe, thunkAPI.rejectWithValue, thunkAPI.extra.userService ); - return await thunk(userId, recipeId); + await thunk(userId, recipe.id); + return recipe; }, ); From 96ca0eae4584e643504813e3cd6b8326d2b8c445 Mon Sep 17 00:00:00 2001 From: akaeyuhi <54174780+akaeyuhi@users.noreply.github.com> Date: Fri, 9 Jun 2023 20:24:51 +0300 Subject: [PATCH 72/73] fix: fixed return types --- .../src/app/actions/account/deleteFavoriteRecipe.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts index 22738c1..fb46831 100644 --- a/src/client/src/app/actions/account/deleteFavoriteRecipe.ts +++ b/src/client/src/app/actions/account/deleteFavoriteRecipe.ts @@ -1,12 +1,13 @@ import { AuthStoreError } from '../../slices/types/Auth/AuthState'; import { createAppAsyncThunk } from '../../utils/createAppAsyncThunk'; import { thunkErrorWrapper } from '../../utils/thunkErrorWrapper'; +import { RecipeModel } from '../../../services/models/RecipeModel'; -export const deleteFavoriteRecipe = createAppAsyncThunk( 'account/deleteFavoriteRecipe', - async ({ recipeId }, thunkAPI) => { + async ({ recipe }, thunkAPI) => { if (!thunkAPI.extra.userService.token) { thunkAPI.extra.userService.setToken(thunkAPI.getState().account.token); } @@ -15,6 +16,7 @@ export const deleteFavoriteRecipe = createAppAsyncThunk Date: Fri, 9 Jun 2023 20:28:02 +0300 Subject: [PATCH 73/73] fix: deleted consts on enums and unused toString overload --- src/client/src/features/ValidationError.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/client/src/features/ValidationError.ts b/src/client/src/features/ValidationError.ts index f1266b5..8137e31 100644 --- a/src/client/src/features/ValidationError.ts +++ b/src/client/src/features/ValidationError.ts @@ -1,10 +1,10 @@ -export const enum ValidationErrors { +export enum ValidationErrors { Email = 'email', Password = 'password', Confirm = 'confirm', } -export const enum ValidationDescriptions { +export enum ValidationDescriptions { Email = 'Invalid email', PasswordShort = 'Password is shorter than 8 symbols', PasswordEmpty = 'Password is required', @@ -37,8 +37,4 @@ export default class ValidationError { )); return validationErrors; } - - toString() { - return this.description; - } }