From 9b85436196d71ca061b944e9b4ee836361432cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sans=C3=A3o=20Araldi?= Date: Wed, 3 Jul 2024 18:36:54 -0300 Subject: [PATCH 01/23] perf: change all components to use `memo` and avoid unnecessary renderings --- .eslintrc.json | 13 +-- CHANGELOG.md | 121 ++++++++++++------------ package-lock.json | 12 +-- package.json | 1 - src/components/Carousel/index.tsx | 22 ++++- src/components/CarouselButton/index.tsx | 8 +- src/components/CarouselEvent/index.tsx | 7 +- src/components/CarouselImage/index.tsx | 6 +- src/components/Footer/index.tsx | 5 +- src/components/GenericButton/index.tsx | 9 +- src/components/Header/index.tsx | 7 +- src/components/Icon/index.tsx | 7 +- src/components/Metric/index.tsx | 8 +- src/components/Modal/index.tsx | 5 +- src/components/ProductCard/index.tsx | 8 +- src/components/SearchInput/index.tsx | 6 +- src/components/Spinner/index.tsx | 5 +- src/components/Text/index.tsx | 6 +- src/components/WhatsAppButton/index.tsx | 6 +- src/components/index.ts | 48 +++++++--- 20 files changed, 182 insertions(+), 128 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index a4d86d3..8d82eb5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -16,19 +16,10 @@ }, "ecmaVersion": "latest" }, - "plugins": [ - "react-refresh", - "@typescript-eslint", - "simple-import-sort", - "prettier" - ], + "plugins": ["@typescript-eslint", "simple-import-sort", "prettier"], "rules": { "prettier/prettier": "error", "simple-import-sort/imports": "error", - "simple-import-sort/exports": "error", - "react-refresh/only-export-components": [ - "warn", - { "allowConstantExport": true } - ] + "simple-import-sort/exports": "error" } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fd9d55..24b6e32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,72 +1,69 @@ # 1.0.0 (2024-07-03) - ### Bug Fixes -* add `textColors` constant to manager colors of `Text` component ([1ce1641](https://github.com/ArtelierMaisa/artelier-maisa/commit/1ce16411952e34ecd34e2d23ce343609c5db115c)) -* add correct `favicon` image ([978ded8](https://github.com/ArtelierMaisa/artelier-maisa/commit/978ded8fec4a8277567ad52178de524c1cff9ac9)) -* add cover to profile image ([54ec48e](https://github.com/ArtelierMaisa/artelier-maisa/commit/54ec48e7aa1c13f6f4f86e059824b199f69f5165)) -* add highlight to tab products when user open platform directly in the `Product` page ([5ae34ab](https://github.com/ArtelierMaisa/artelier-maisa/commit/5ae34ab8ceed56646f410df78ec89718a281b206)) -* add safe `z-index` to overlay in `Modal` component ([903f119](https://github.com/ArtelierMaisa/artelier-maisa/commit/903f1196df4e0f94397a7043ed9178178f2769f3)) -* add scroll Y auto to `Modal` component and custom style ([29587f8](https://github.com/ArtelierMaisa/artelier-maisa/commit/29587f829131444bdd45eeeef4cdcd603ad7280c)) -* adjust in `SendMessageProps` interface when its used by `WhatsAppButton` and `Footer` ([5403d73](https://github.com/ArtelierMaisa/artelier-maisa/commit/5403d73a8dce639620668f57cf7fc3c94a304c4e)) -* bigger adjusts in colors and sizes of `Icon` types component, and size of `Text` component ([9402a49](https://github.com/ArtelierMaisa/artelier-maisa/commit/9402a49b647f8b2154591690b35e0036cfb842a6)) -* improve `Text` component and add responsiveness to `Footer` component ([c0218bc](https://github.com/ArtelierMaisa/artelier-maisa/commit/c0218bc18f87166fe96363692602443925a03787)) -* release 1.0.3 ([48dd83d](https://github.com/ArtelierMaisa/artelier-maisa/commit/48dd83d9ca8f5bee52cb61293c34a8362b8f6233)) -* remove Uri import ([4d933b6](https://github.com/ArtelierMaisa/artelier-maisa/commit/4d933b6917b545125a347be074f63d58c722d39b)) -* resolve problem when products doesn't exists in category ([d2d625e](https://github.com/ArtelierMaisa/artelier-maisa/commit/d2d625e25fc61b01e427c4432cd790e14786f8ca)) -* small adjust in favicon path image ([9da52a1](https://github.com/ArtelierMaisa/artelier-maisa/commit/9da52a185b75191f635188e411842056fd675a4d)) - +- add `textColors` constant to manager colors of `Text` component ([1ce1641](https://github.com/ArtelierMaisa/artelier-maisa/commit/1ce16411952e34ecd34e2d23ce343609c5db115c)) +- add correct `favicon` image ([978ded8](https://github.com/ArtelierMaisa/artelier-maisa/commit/978ded8fec4a8277567ad52178de524c1cff9ac9)) +- add cover to profile image ([54ec48e](https://github.com/ArtelierMaisa/artelier-maisa/commit/54ec48e7aa1c13f6f4f86e059824b199f69f5165)) +- add highlight to tab products when user open platform directly in the `Product` page ([5ae34ab](https://github.com/ArtelierMaisa/artelier-maisa/commit/5ae34ab8ceed56646f410df78ec89718a281b206)) +- add safe `z-index` to overlay in `Modal` component ([903f119](https://github.com/ArtelierMaisa/artelier-maisa/commit/903f1196df4e0f94397a7043ed9178178f2769f3)) +- add scroll Y auto to `Modal` component and custom style ([29587f8](https://github.com/ArtelierMaisa/artelier-maisa/commit/29587f829131444bdd45eeeef4cdcd603ad7280c)) +- adjust in `SendMessageProps` interface when its used by `WhatsAppButton` and `Footer` ([5403d73](https://github.com/ArtelierMaisa/artelier-maisa/commit/5403d73a8dce639620668f57cf7fc3c94a304c4e)) +- bigger adjusts in colors and sizes of `Icon` types component, and size of `Text` component ([9402a49](https://github.com/ArtelierMaisa/artelier-maisa/commit/9402a49b647f8b2154591690b35e0036cfb842a6)) +- improve `Text` component and add responsiveness to `Footer` component ([c0218bc](https://github.com/ArtelierMaisa/artelier-maisa/commit/c0218bc18f87166fe96363692602443925a03787)) +- release 1.0.3 ([48dd83d](https://github.com/ArtelierMaisa/artelier-maisa/commit/48dd83d9ca8f5bee52cb61293c34a8362b8f6233)) +- remove Uri import ([4d933b6](https://github.com/ArtelierMaisa/artelier-maisa/commit/4d933b6917b545125a347be074f63d58c722d39b)) +- resolve problem when products doesn't exists in category ([d2d625e](https://github.com/ArtelierMaisa/artelier-maisa/commit/d2d625e25fc61b01e427c4432cd790e14786f8ca)) +- small adjust in favicon path image ([9da52a1](https://github.com/ArtelierMaisa/artelier-maisa/commit/9da52a185b75191f635188e411842056fd675a4d)) ### Features -* add `.env.example` ([84922f8](https://github.com/ArtelierMaisa/artelier-maisa/commit/84922f84ed80baf438637f4ee5749a906972d32b)) -* add `CarouselButton` and `Carousel` components ([8e2e052](https://github.com/ArtelierMaisa/artelier-maisa/commit/8e2e05253e7e518186454ea823cf749fa1800e33)) -* add `CarouselEvent` component and small style adjust in `ProductCard` component ([c2580c7](https://github.com/ArtelierMaisa/artelier-maisa/commit/c2580c7bdb5aab85d92f2bf74638a11884f86409)) -* add `CarouselImage` component ([fa1a946](https://github.com/ArtelierMaisa/artelier-maisa/commit/fa1a946cb4931745261625b4fd7e6d9fa31c68e1)) -* add `firabase` config ([c6458ea](https://github.com/ArtelierMaisa/artelier-maisa/commit/c6458eac190a47f54abcd09075d93195030815d4)) -* add `flowbite` and `flowbite-react` config ([2eb6203](https://github.com/ArtelierMaisa/artelier-maisa/commit/2eb6203d62d9b850e10abda07b7a73eebba35245)) -* add `Footer` component ([ac105b9](https://github.com/ArtelierMaisa/artelier-maisa/commit/ac105b986893761ace626b363779d35b41a112dc)) -* add `GenericButton` component ([a86f529](https://github.com/ArtelierMaisa/artelier-maisa/commit/a86f5298e2c6653fea84a1db4219f2ca8c8d5b25)) -* add `Header` component ([dd0d4b9](https://github.com/ArtelierMaisa/artelier-maisa/commit/dd0d4b925f78cb447087b372b5a4849fd299e31f)) -* add `inter` font to tailwind ([125f10c](https://github.com/ArtelierMaisa/artelier-maisa/commit/125f10c0f17a90aafa1b323bef74b78146c7a9a4)) -* add `isLoading` property to `GenericButton` component ([a38c559](https://github.com/ArtelierMaisa/artelier-maisa/commit/a38c55945eff5f65b5cb055046a4f3965a39b25b)) -* add `Metric` component and custom `box-shadow` in `tailwindcss` ([f1646e5](https://github.com/ArtelierMaisa/artelier-maisa/commit/f1646e5e1a95b0bee13776a0d49f6898b9b67997)) -* add `Modal` component ([2458bea](https://github.com/ArtelierMaisa/artelier-maisa/commit/2458bea6e85aa731268f1cf6373a98350404ef6e)) -* add `Modal` component and `tailwind-scrollbar` plugin ([5e535b5](https://github.com/ArtelierMaisa/artelier-maisa/commit/5e535b5d07f0b8e90e4070bff2777e7c229ea196)) -* add `NotFound` page ([63523b7](https://github.com/ArtelierMaisa/artelier-maisa/commit/63523b7efc9a155c1315381b1b6d3729e6cb01ef)) -* add `ProductCard` component ([af05290](https://github.com/ArtelierMaisa/artelier-maisa/commit/af05290efabdb78f37506f9212f1bba736d163b2)) -* add `react-scroll` for scroll to correctly section in structure of landing page ([2e4ee45](https://github.com/ArtelierMaisa/artelier-maisa/commit/2e4ee45b20114788f2cb6ddf34fd625ec0d17cde)) -* add `ScrollTopContext` and `useScrollTop` to when we go back from `Products` page ([a14ef70](https://github.com/ArtelierMaisa/artelier-maisa/commit/a14ef700a6ce3f8aafd7b4d62e1a15e7ec62491c)) -* add `SearchInput` component ([a6abe6e](https://github.com/ArtelierMaisa/artelier-maisa/commit/a6abe6ecbc211a0c28a96f26a78076f39c8a6280)) -* add `Spinner` component ([cd57837](https://github.com/ArtelierMaisa/artelier-maisa/commit/cd578373a63b0e71ee9e9e236a782eb3e21e6983)) -* add `tailwindcss ` and setup colors ([afd6e85](https://github.com/ArtelierMaisa/artelier-maisa/commit/afd6e85942776176400409243bee14305eb04a33)) -* add `useUser` hook to handle with user requests ([08c29c9](https://github.com/ArtelierMaisa/artelier-maisa/commit/08c29c9ef3e2fd69f7f2422e33fa6c51c18598fa)) -* add `weights` and `sizes` of `Text` component in `constants` folder ([f83e82c](https://github.com/ArtelierMaisa/artelier-maisa/commit/f83e82cdf2b9ad33bf96c903bf82e3813d88753f)) -* add `WhatsAppButton` component ([c03307a](https://github.com/ArtelierMaisa/artelier-maisa/commit/c03307a46ffeab70b60627d7730f6ad3734ae366)) -* add conditional to show `additional` of the about in `LandingPage` ([309c8e9](https://github.com/ArtelierMaisa/artelier-maisa/commit/309c8e99266014b3f19593d74cfbe7dbcd2b5663)) -* add default phone and email ([e955c99](https://github.com/ArtelierMaisa/artelier-maisa/commit/e955c99fd30b8d6b1189a39882147b359cfd3677)) -* add integration in the `Products` page ([728339e](https://github.com/ArtelierMaisa/artelier-maisa/commit/728339ee590d17c6708887164bf981fea6da0c09)) -* add integration with banners ([2ad30de](https://github.com/ArtelierMaisa/artelier-maisa/commit/2ad30ded2d1d4aae0507673891d5fd3d9dc9ee51)) -* add integration with highlight data ([0e5086f](https://github.com/ArtelierMaisa/artelier-maisa/commit/0e5086f39ef838f6ba820ce01ee092123a5db085)) -* add integration with WhatsApp API ([18303e5](https://github.com/ArtelierMaisa/artelier-maisa/commit/18303e56414cc868d2fa527a11e3fad818a6fc3b)) -* add mail to in envelope icon in the `Footer` component ([99d3e86](https://github.com/ArtelierMaisa/artelier-maisa/commit/99d3e86d5ae4b6e4dc5f74c7e4752d362a2067c9)) -* add products to `LandingPage` ([997699e](https://github.com/ArtelierMaisa/artelier-maisa/commit/997699e59ea4c34f7f8b4ed86e044a1365a6f66a)) -* add project logo ([38fd301](https://github.com/ArtelierMaisa/artelier-maisa/commit/38fd301a299623c89b0ad55843bb2697da1d7895)) -* add routes in `App` ([f0886c0](https://github.com/ArtelierMaisa/artelier-maisa/commit/f0886c00398dd3c2bba1bf5f535be78c19e745ce)) -* add support ts to images ([c0dfd4e](https://github.com/ArtelierMaisa/artelier-maisa/commit/c0dfd4e391f7b39401e3d0420b27e0dee80e06f8)) -* create `envs` file to manager all environment variables ([8f58e8a](https://github.com/ArtelierMaisa/artelier-maisa/commit/8f58e8a82651678c003c49a96b80fd0c1f61f657)) -* create `react` project with `vite` ([597aab4](https://github.com/ArtelierMaisa/artelier-maisa/commit/597aab4465565f84ca35b9a753067d7e484dc515)) -* create `Text` component ([7d9551a](https://github.com/ArtelierMaisa/artelier-maisa/commit/7d9551a1a0f76cd951df7250b44ba3eed14ff2ae)) -* create Icon component ([01df400](https://github.com/ArtelierMaisa/artelier-maisa/commit/01df400fcbdafcf31423c7dc03848a41aae0ce7b)) -* finish `LandingPage` structure and style ([06a1697](https://github.com/ArtelierMaisa/artelier-maisa/commit/06a1697e2e3ed5afdd4398ea16add925d7f7d5a5)) -* finish structure and styles from Products page ([ebdeff4](https://github.com/ArtelierMaisa/artelier-maisa/commit/ebdeff4ae320a11ae5aaab56de030fdc666b2685)) -* integrate `Header` component with `react-router-dom` ([26891c9](https://github.com/ArtelierMaisa/artelier-maisa/commit/26891c911a541381c101332a75c8ed80b5144141)) -* release 1.0.0 ([152a936](https://github.com/ArtelierMaisa/artelier-maisa/commit/152a9361cedba93aac9d738918830cce424fa62e)) -* release 1.0.1 ([4a419f5](https://github.com/ArtelierMaisa/artelier-maisa/commit/4a419f5135d7875f19b7e1ef86a940d339252559)) -* release 1.0.2 ([6415cef](https://github.com/ArtelierMaisa/artelier-maisa/commit/6415cef7178b58e41592d2ac1dfbedbaba60ae01)) - +- add `.env.example` ([84922f8](https://github.com/ArtelierMaisa/artelier-maisa/commit/84922f84ed80baf438637f4ee5749a906972d32b)) +- add `CarouselButton` and `Carousel` components ([8e2e052](https://github.com/ArtelierMaisa/artelier-maisa/commit/8e2e05253e7e518186454ea823cf749fa1800e33)) +- add `CarouselEvent` component and small style adjust in `ProductCard` component ([c2580c7](https://github.com/ArtelierMaisa/artelier-maisa/commit/c2580c7bdb5aab85d92f2bf74638a11884f86409)) +- add `CarouselImage` component ([fa1a946](https://github.com/ArtelierMaisa/artelier-maisa/commit/fa1a946cb4931745261625b4fd7e6d9fa31c68e1)) +- add `firabase` config ([c6458ea](https://github.com/ArtelierMaisa/artelier-maisa/commit/c6458eac190a47f54abcd09075d93195030815d4)) +- add `flowbite` and `flowbite-react` config ([2eb6203](https://github.com/ArtelierMaisa/artelier-maisa/commit/2eb6203d62d9b850e10abda07b7a73eebba35245)) +- add `Footer` component ([ac105b9](https://github.com/ArtelierMaisa/artelier-maisa/commit/ac105b986893761ace626b363779d35b41a112dc)) +- add `GenericButton` component ([a86f529](https://github.com/ArtelierMaisa/artelier-maisa/commit/a86f5298e2c6653fea84a1db4219f2ca8c8d5b25)) +- add `Header` component ([dd0d4b9](https://github.com/ArtelierMaisa/artelier-maisa/commit/dd0d4b925f78cb447087b372b5a4849fd299e31f)) +- add `inter` font to tailwind ([125f10c](https://github.com/ArtelierMaisa/artelier-maisa/commit/125f10c0f17a90aafa1b323bef74b78146c7a9a4)) +- add `isLoading` property to `GenericButton` component ([a38c559](https://github.com/ArtelierMaisa/artelier-maisa/commit/a38c55945eff5f65b5cb055046a4f3965a39b25b)) +- add `Metric` component and custom `box-shadow` in `tailwindcss` ([f1646e5](https://github.com/ArtelierMaisa/artelier-maisa/commit/f1646e5e1a95b0bee13776a0d49f6898b9b67997)) +- add `Modal` component ([2458bea](https://github.com/ArtelierMaisa/artelier-maisa/commit/2458bea6e85aa731268f1cf6373a98350404ef6e)) +- add `Modal` component and `tailwind-scrollbar` plugin ([5e535b5](https://github.com/ArtelierMaisa/artelier-maisa/commit/5e535b5d07f0b8e90e4070bff2777e7c229ea196)) +- add `NotFound` page ([63523b7](https://github.com/ArtelierMaisa/artelier-maisa/commit/63523b7efc9a155c1315381b1b6d3729e6cb01ef)) +- add `ProductCard` component ([af05290](https://github.com/ArtelierMaisa/artelier-maisa/commit/af05290efabdb78f37506f9212f1bba736d163b2)) +- add `react-scroll` for scroll to correctly section in structure of landing page ([2e4ee45](https://github.com/ArtelierMaisa/artelier-maisa/commit/2e4ee45b20114788f2cb6ddf34fd625ec0d17cde)) +- add `ScrollTopContext` and `useScrollTop` to when we go back from `Products` page ([a14ef70](https://github.com/ArtelierMaisa/artelier-maisa/commit/a14ef700a6ce3f8aafd7b4d62e1a15e7ec62491c)) +- add `SearchInput` component ([a6abe6e](https://github.com/ArtelierMaisa/artelier-maisa/commit/a6abe6ecbc211a0c28a96f26a78076f39c8a6280)) +- add `Spinner` component ([cd57837](https://github.com/ArtelierMaisa/artelier-maisa/commit/cd578373a63b0e71ee9e9e236a782eb3e21e6983)) +- add `tailwindcss ` and setup colors ([afd6e85](https://github.com/ArtelierMaisa/artelier-maisa/commit/afd6e85942776176400409243bee14305eb04a33)) +- add `useUser` hook to handle with user requests ([08c29c9](https://github.com/ArtelierMaisa/artelier-maisa/commit/08c29c9ef3e2fd69f7f2422e33fa6c51c18598fa)) +- add `weights` and `sizes` of `Text` component in `constants` folder ([f83e82c](https://github.com/ArtelierMaisa/artelier-maisa/commit/f83e82cdf2b9ad33bf96c903bf82e3813d88753f)) +- add `WhatsAppButton` component ([c03307a](https://github.com/ArtelierMaisa/artelier-maisa/commit/c03307a46ffeab70b60627d7730f6ad3734ae366)) +- add conditional to show `additional` of the about in `LandingPage` ([309c8e9](https://github.com/ArtelierMaisa/artelier-maisa/commit/309c8e99266014b3f19593d74cfbe7dbcd2b5663)) +- add default phone and email ([e955c99](https://github.com/ArtelierMaisa/artelier-maisa/commit/e955c99fd30b8d6b1189a39882147b359cfd3677)) +- add integration in the `Products` page ([728339e](https://github.com/ArtelierMaisa/artelier-maisa/commit/728339ee590d17c6708887164bf981fea6da0c09)) +- add integration with banners ([2ad30de](https://github.com/ArtelierMaisa/artelier-maisa/commit/2ad30ded2d1d4aae0507673891d5fd3d9dc9ee51)) +- add integration with highlight data ([0e5086f](https://github.com/ArtelierMaisa/artelier-maisa/commit/0e5086f39ef838f6ba820ce01ee092123a5db085)) +- add integration with WhatsApp API ([18303e5](https://github.com/ArtelierMaisa/artelier-maisa/commit/18303e56414cc868d2fa527a11e3fad818a6fc3b)) +- add mail to in envelope icon in the `Footer` component ([99d3e86](https://github.com/ArtelierMaisa/artelier-maisa/commit/99d3e86d5ae4b6e4dc5f74c7e4752d362a2067c9)) +- add products to `LandingPage` ([997699e](https://github.com/ArtelierMaisa/artelier-maisa/commit/997699e59ea4c34f7f8b4ed86e044a1365a6f66a)) +- add project logo ([38fd301](https://github.com/ArtelierMaisa/artelier-maisa/commit/38fd301a299623c89b0ad55843bb2697da1d7895)) +- add routes in `App` ([f0886c0](https://github.com/ArtelierMaisa/artelier-maisa/commit/f0886c00398dd3c2bba1bf5f535be78c19e745ce)) +- add support ts to images ([c0dfd4e](https://github.com/ArtelierMaisa/artelier-maisa/commit/c0dfd4e391f7b39401e3d0420b27e0dee80e06f8)) +- create `envs` file to manager all environment variables ([8f58e8a](https://github.com/ArtelierMaisa/artelier-maisa/commit/8f58e8a82651678c003c49a96b80fd0c1f61f657)) +- create `react` project with `vite` ([597aab4](https://github.com/ArtelierMaisa/artelier-maisa/commit/597aab4465565f84ca35b9a753067d7e484dc515)) +- create `Text` component ([7d9551a](https://github.com/ArtelierMaisa/artelier-maisa/commit/7d9551a1a0f76cd951df7250b44ba3eed14ff2ae)) +- create Icon component ([01df400](https://github.com/ArtelierMaisa/artelier-maisa/commit/01df400fcbdafcf31423c7dc03848a41aae0ce7b)) +- finish `LandingPage` structure and style ([06a1697](https://github.com/ArtelierMaisa/artelier-maisa/commit/06a1697e2e3ed5afdd4398ea16add925d7f7d5a5)) +- finish structure and styles from Products page ([ebdeff4](https://github.com/ArtelierMaisa/artelier-maisa/commit/ebdeff4ae320a11ae5aaab56de030fdc666b2685)) +- integrate `Header` component with `react-router-dom` ([26891c9](https://github.com/ArtelierMaisa/artelier-maisa/commit/26891c911a541381c101332a75c8ed80b5144141)) +- release 1.0.0 ([152a936](https://github.com/ArtelierMaisa/artelier-maisa/commit/152a9361cedba93aac9d738918830cce424fa62e)) +- release 1.0.1 ([4a419f5](https://github.com/ArtelierMaisa/artelier-maisa/commit/4a419f5135d7875f19b7e1ef86a940d339252559)) +- release 1.0.2 ([6415cef](https://github.com/ArtelierMaisa/artelier-maisa/commit/6415cef7178b58e41592d2ac1dfbedbaba60ae01)) ### Performance Improvements -* change `Text` to span when it's a text inside text ([10969e1](https://github.com/ArtelierMaisa/artelier-maisa/commit/10969e1681bbdd92e50eba35fc209420392fb58c)) +- change `Text` to span when it's a text inside text ([10969e1](https://github.com/ArtelierMaisa/artelier-maisa/commit/10969e1681bbdd92e50eba35fc209420392fb58c)) diff --git a/package-lock.json b/package-lock.json index 41bea3d..5430933 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,6 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.6", "eslint-plugin-simple-import-sort": "^12.1.0", "git-commit-msg-linter": "^5.0.7", "husky": "^9.0.11", @@ -53,7 +52,7 @@ "vite": "^5.2.0" }, "engines": { - "node": ">= 20.11.x" + "node": ">= 20.x" } }, "node_modules/@alloc/quick-lru": { @@ -4777,15 +4776,6 @@ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.6.tgz", - "integrity": "sha512-NjGXdm7zgcKRkKMua34qVO9doI7VOxZ6ancSvBELJSSoX97jyndXcSoa8XBh69JoB31dNz3EEzlMcizZl7LaMA==", - "dev": true, - "peerDependencies": { - "eslint": ">=7" - } - }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", diff --git a/package.json b/package.json index beb520b..98c460f 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.6", "eslint-plugin-simple-import-sort": "^12.1.0", "git-commit-msg-linter": "^5.0.7", "husky": "^9.0.11", diff --git a/src/components/Carousel/index.tsx b/src/components/Carousel/index.tsx index 63c1c19..160b062 100644 --- a/src/components/Carousel/index.tsx +++ b/src/components/Carousel/index.tsx @@ -1,10 +1,11 @@ import { Carousel as FlowbiteCarousel } from 'flowbite-react'; +import { memo } from 'react'; import { CarouselProps } from '../../@types'; import { carouselHeights } from '../../constants'; -import { CarouselButton } from '../CarouselButton'; +import { CarouselButton } from '../'; -export function Carousel(props: CarouselProps) { +function Carousel(props: CarouselProps) { const { children, type = 'banner', @@ -18,17 +19,30 @@ export function Carousel(props: CarouselProps) { const isBanner = type === 'banner'; const slideInterval = isBanner ? 3000 : 5000; + const rightControl: React.JSX.Element = !hasChildren ? ( + + ) : ( + + ); + const leftControl: React.JSX.Element = !hasChildren ? ( + + ) : ( + + ); + return (
} - leftControl={} + rightControl={rightControl} + leftControl={leftControl} > {children}
); } + +export default memo(Carousel); diff --git a/src/components/CarouselButton/index.tsx b/src/components/CarouselButton/index.tsx index 73f8f7d..bd6fc9c 100644 --- a/src/components/CarouselButton/index.tsx +++ b/src/components/CarouselButton/index.tsx @@ -1,11 +1,13 @@ +import { memo } from 'react'; + import { CarouselButtonProps, CarouselButtonType, IconProps, } from '../../@types'; -import { Icon } from '../Icon'; +import { Icon } from '../'; -export function CarouselButton(props: CarouselButtonProps) { +function CarouselButton(props: CarouselButtonProps) { const { type } = props; const isNext = type === 'next'; @@ -30,3 +32,5 @@ export function CarouselButton(props: CarouselButtonProps) { ); } + +export default memo(CarouselButton); diff --git a/src/components/CarouselEvent/index.tsx b/src/components/CarouselEvent/index.tsx index ee9ef26..ed4e1f3 100644 --- a/src/components/CarouselEvent/index.tsx +++ b/src/components/CarouselEvent/index.tsx @@ -1,9 +1,10 @@ import { Card } from 'flowbite-react'; +import { memo } from 'react'; import { CarouselEventProps } from '../../@types'; -import { Text } from '../Text'; +import { Text } from '../'; -export function CarouselEvent(props: CarouselEventProps) { +function CarouselEvent(props: CarouselEventProps) { const { description, image, title } = props; return ( @@ -36,3 +37,5 @@ export function CarouselEvent(props: CarouselEventProps) { ); } + +export default memo(CarouselEvent); diff --git a/src/components/CarouselImage/index.tsx b/src/components/CarouselImage/index.tsx index 814f4ba..eb7754b 100644 --- a/src/components/CarouselImage/index.tsx +++ b/src/components/CarouselImage/index.tsx @@ -1,6 +1,8 @@ +import { memo } from 'react'; + import { CarouselImageProps } from '../../@types'; -export function CarouselImage(props: CarouselImageProps) { +function CarouselImage(props: CarouselImageProps) { const { id, uri } = props; return ( @@ -12,3 +14,5 @@ export function CarouselImage(props: CarouselImageProps) { /> ); } + +export default memo(CarouselImage); diff --git a/src/components/Footer/index.tsx b/src/components/Footer/index.tsx index dc8a47a..f3d4075 100644 --- a/src/components/Footer/index.tsx +++ b/src/components/Footer/index.tsx @@ -1,4 +1,5 @@ import { Footer as FlowbiteFooter } from 'flowbite-react'; +import { memo } from 'react'; import packageJson from '../../../package.json'; import { IconProps } from '../../@types'; @@ -6,7 +7,7 @@ import { DEFAULT_EMAIL } from '../../config'; import { sendMessage } from '../../utils'; import { Icon, Text } from '../'; -export function Footer() { +function Footer() { const version = packageJson.version; const currentYear = new Date().getFullYear(); @@ -98,3 +99,5 @@ export function Footer() { ); } + +export default memo(Footer); diff --git a/src/components/GenericButton/index.tsx b/src/components/GenericButton/index.tsx index 2badeeb..8375146 100644 --- a/src/components/GenericButton/index.tsx +++ b/src/components/GenericButton/index.tsx @@ -1,9 +1,10 @@ +import { memo } from 'react'; + import { Colors, GenericButtonProps, SpinnerColor } from '../../@types'; import { genericButtonHeights } from '../../constants'; -import { Spinner } from '../Spinner'; -import { Text } from '../Text'; +import { Spinner, Text } from '../'; -export function GenericButton(props: GenericButtonProps) { +function GenericButton(props: GenericButtonProps) { const { title, variant = 'primary', @@ -67,3 +68,5 @@ export function GenericButton(props: GenericButtonProps) { ); } + +export default memo(GenericButton); diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index d598223..621833b 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,12 +1,13 @@ import { Navbar } from 'flowbite-react'; +import { memo } from 'react'; import { Link } from 'react-scroll'; import { TextProps } from '../../@types'; import { PRIMARY_LOGO } from '../../config'; import { useScrollTop, useUser } from '../../hooks'; -import { Text } from '../Text'; +import { Text } from '../'; -export function Header() { +function Header() { const { highlights } = useUser(); const { handleTo, to } = useScrollTop(); @@ -87,3 +88,5 @@ export function Header() { ); } + +export default memo(Header); diff --git a/src/components/Icon/index.tsx b/src/components/Icon/index.tsx index e5c58ff..1802d96 100644 --- a/src/components/Icon/index.tsx +++ b/src/components/Icon/index.tsx @@ -12,11 +12,12 @@ import { WhatsappLogo, X, } from '@phosphor-icons/react'; +import { memo } from 'react'; import { IconProps } from '../../@types'; -import { iconColors, iconSizes } from '../../constants/components'; +import { iconColors, iconSizes } from '../../constants'; -export function Icon(props: IconProps) { +function Icon(props: IconProps) { const { variant, color = 'background-color', @@ -49,3 +50,5 @@ export function Icon(props: IconProps) { return icons[variant]; } + +export default memo(Icon); diff --git a/src/components/Metric/index.tsx b/src/components/Metric/index.tsx index d6ab10f..7603312 100644 --- a/src/components/Metric/index.tsx +++ b/src/components/Metric/index.tsx @@ -1,8 +1,10 @@ +import { memo } from 'react'; + import { MetricProps } from '../../@types'; import { metricsVariants } from '../../constants'; -import { Text } from '../Text'; +import { Text } from '../'; -export function Metric(props: MetricProps) { +function Metric(props: MetricProps) { const { value, variant = 'material' } = props; return ( @@ -33,3 +35,5 @@ export function Metric(props: MetricProps) { ); } + +export default memo(Metric); diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx index 8ae706a..8b1ccf3 100644 --- a/src/components/Modal/index.tsx +++ b/src/components/Modal/index.tsx @@ -1,3 +1,4 @@ +import { memo } from 'react'; import ReactModal from 'react-modal'; import { ModalProps } from '../../@types'; @@ -10,7 +11,7 @@ import { WhatsAppButton, } from '../'; -export function Modal(props: ModalProps) { +function Modal(props: ModalProps) { const { isOpen, product, onClose } = props; const hasMetrics = !!product.size || !!product.weight || !!product.material; @@ -70,3 +71,5 @@ export function Modal(props: ModalProps) { ); } + +export default memo(Modal); diff --git a/src/components/ProductCard/index.tsx b/src/components/ProductCard/index.tsx index a593e08..6823788 100644 --- a/src/components/ProductCard/index.tsx +++ b/src/components/ProductCard/index.tsx @@ -1,10 +1,10 @@ import { Card } from 'flowbite-react'; +import { memo } from 'react'; import { ProductCardProps } from '../../@types'; -import { GenericButton } from '../GenericButton'; -import { Text } from '../Text'; +import { GenericButton, Text } from '../'; -export function ProductCard(props: ProductCardProps) { +function ProductCard(props: ProductCardProps) { const { id, name, description, price, image, onSeeMore } = props; return ( @@ -40,3 +40,5 @@ export function ProductCard(props: ProductCardProps) { ); } + +export default memo(ProductCard); diff --git a/src/components/SearchInput/index.tsx b/src/components/SearchInput/index.tsx index cad2317..47a6cc9 100644 --- a/src/components/SearchInput/index.tsx +++ b/src/components/SearchInput/index.tsx @@ -1,9 +1,9 @@ -import { useState } from 'react'; +import { memo, useState } from 'react'; import { SearchInputCategoryProps, SearchInputProps } from '../../@types'; import { GenericButton, Icon, Text } from '../'; -export function SearchInput(props: SearchInputProps) { +function SearchInput(props: SearchInputProps) { const { categories, searchValue, onChange, onSelect, onSearch } = props; const [showDropdown, setShowDropdown] = useState(false); @@ -101,3 +101,5 @@ export function SearchInput(props: SearchInputProps) { ); } + +export default memo(SearchInput); diff --git a/src/components/Spinner/index.tsx b/src/components/Spinner/index.tsx index 0de81af..42f3b8f 100644 --- a/src/components/Spinner/index.tsx +++ b/src/components/Spinner/index.tsx @@ -1,9 +1,10 @@ import { Spinner as FlowbiteSpinner } from 'flowbite-react'; +import { memo } from 'react'; import { SpinnerProps } from '../../@types'; import { spinnerSizes } from '../../constants'; -export function Spinner(props: SpinnerProps) { +function Spinner(props: SpinnerProps) { const { size = 'medium', color = 'primary' } = props; return ( @@ -14,3 +15,5 @@ export function Spinner(props: SpinnerProps) { /> ); } + +export default memo(Spinner); diff --git a/src/components/Text/index.tsx b/src/components/Text/index.tsx index 126f9d8..6e46e63 100644 --- a/src/components/Text/index.tsx +++ b/src/components/Text/index.tsx @@ -1,3 +1,5 @@ +import { memo } from 'react'; + import { TextProps } from '../../@types'; import { textColors, @@ -7,7 +9,7 @@ import { textWeights, } from '../../constants'; -export function Text(props: TextProps) { +function Text(props: TextProps) { const { children, type = 'regular', @@ -35,3 +37,5 @@ export function Text(props: TextProps) {

); } + +export default memo(Text); diff --git a/src/components/WhatsAppButton/index.tsx b/src/components/WhatsAppButton/index.tsx index f48a0bc..3ad9653 100644 --- a/src/components/WhatsAppButton/index.tsx +++ b/src/components/WhatsAppButton/index.tsx @@ -1,9 +1,11 @@ +import { memo } from 'react'; + import { WhatsAppButtonProps } from '../../@types'; import { DEFAULT_PHONE } from '../../config'; import { sendMessage } from '../../utils'; import { Icon, Text } from '../'; -export function WhatsAppButton(props: WhatsAppButtonProps) { +function WhatsAppButton(props: WhatsAppButtonProps) { const { product, phone = DEFAULT_PHONE } = props; function onSendWhatsAppMessage(): void { @@ -29,3 +31,5 @@ export function WhatsAppButton(props: WhatsAppButtonProps) { ); } + +export default memo(WhatsAppButton); diff --git a/src/components/index.ts b/src/components/index.ts index 8be13f4..58a8b7a 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,15 +1,33 @@ -export * from './Carousel'; -export * from './CarouselButton'; -export * from './CarouselEvent'; -export * from './CarouselImage'; -export * from './Footer'; -export * from './GenericButton'; -export * from './Header'; -export * from './Icon'; -export * from './Metric'; -export * from './Modal'; -export * from './ProductCard'; -export * from './SearchInput'; -export * from './Spinner'; -export * from './Text'; -export * from './WhatsAppButton'; +import Carousel from './Carousel'; +import CarouselButton from './CarouselButton'; +import CarouselEvent from './CarouselEvent'; +import CarouselImage from './CarouselImage'; +import Footer from './Footer'; +import GenericButton from './GenericButton'; +import Header from './Header'; +import Icon from './Icon'; +import Metric from './Metric'; +import Modal from './Modal'; +import ProductCard from './ProductCard'; +import SearchInput from './SearchInput'; +import Spinner from './Spinner'; +import Text from './Text'; +import WhatsAppButton from './WhatsAppButton'; + +export { + Carousel, + CarouselButton, + CarouselEvent, + CarouselImage, + Footer, + GenericButton, + Header, + Icon, + Metric, + Modal, + ProductCard, + SearchInput, + Spinner, + Text, + WhatsAppButton, +}; From 58b13d6a0e94881c44eaae71d1da74696fe559c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sans=C3=A3o=20Araldi?= Date: Wed, 3 Jul 2024 18:57:37 -0300 Subject: [PATCH 02/23] perf: add change all `get` firebase function to `onValue` --- src/contexts/UserContext.tsx | 140 ++++++++++++++++------------------- 1 file changed, 63 insertions(+), 77 deletions(-) diff --git a/src/contexts/UserContext.tsx b/src/contexts/UserContext.tsx index a421146..502138d 100644 --- a/src/contexts/UserContext.tsx +++ b/src/contexts/UserContext.tsx @@ -1,11 +1,5 @@ -import { get, onValue, ref, remove } from 'firebase/database'; -import { - createContext, - PropsWithChildren, - useCallback, - useEffect, - useState, -} from 'react'; +import { onValue, ref, remove } from 'firebase/database'; +import { createContext, PropsWithChildren, useEffect, useState } from 'react'; import { toast } from 'sonner'; import { @@ -20,10 +14,8 @@ import { categoryMapper } from '../helpers'; import { database } from '../services'; import { mapper } from '../utils'; -// TODO: Create type to UserContext in @types/contexts. export const UserContext = createContext({} as UserContextProps); -// TODO: Create the data user logic. Add all requests and states this context. export function UserProvider({ children }: Required) { const [isLoaded, setIsLoaded] = useState(false); const [highlights, setHighlights] = useState([]); @@ -37,6 +29,10 @@ export function UserProvider({ children }: Required) { return currentTime > highlight.removedAt; } + function sortProducts(product: Product, productCompare: Product): number { + return productCompare.createdAt - product.createdAt; + } + function handleGenericErrorToast(): void { toast.error( 'Falha ao buscar suas informações! Algo deu errado durante a busca de informações. Por favor, tente novamente. Se o problema persistir, entre em contato com o suporte técnico.', @@ -44,78 +40,26 @@ export function UserProvider({ children }: Required) { ); } - const handleGetAbout = useCallback(async () => { - const aboutRef = ref(database, 'about'); - const aboutSnapshot = await get(aboutRef); - - if (!aboutSnapshot.exists()) return handleGenericErrorToast(); - - const aboutFirebase = mapper(aboutSnapshot)[0]; - - if (!aboutFirebase) return handleGenericErrorToast(); - - setAbout(aboutFirebase); - }, []); - - const handleGetHighlights = useCallback(async () => { + useEffect(() => { + const bannersRef = ref(database, 'banners'); + const categoriesRef = ref(database, 'categories'); const highlightsRef = ref(database, 'highlights'); - const highlightsSnapshot = await get(highlightsRef); - - if (!highlightsSnapshot.exists()) return setHighlights([]); - - const highlightsFirebase = mapper(highlightsSnapshot); - - if (!highlightsFirebase) return handleGenericErrorToast(); + const aboutRef = ref(database, 'about'); - // TODO -> REMOVE HIGHLIGHTS IMAGES FROM FIREBASE STORAGE - highlightsFirebase.forEach(async highlight => { - if (isGreaterThanPeriodRemove(highlight)) { - const highlightRef = ref(database, `highlights/${highlight.id}`); - remove(highlightRef); + const unsubscribeBanners = onValue(bannersRef, bannersSnapshot => { + if (!bannersSnapshot.exists()) { + setBanners([]); + return handleGenericErrorToast(); } - }); - - const highlightsInPeriod = highlightsFirebase.filter( - highlight => !isGreaterThanPeriodRemove(highlight), - ); - - setHighlights(highlightsInPeriod); - }, []); - - const handleGetBanners = useCallback(async () => { - const bannersRef = ref(database, 'banners'); - const bannersSnapshot = await get(bannersRef); - - if (!bannersSnapshot.exists()) return handleGenericErrorToast(); - - const bannersFirebase = mapper(bannersSnapshot); - if (!bannersFirebase) return handleGenericErrorToast(); + const bannersFirebase = mapper(bannersSnapshot); + if (!bannersFirebase) return handleGenericErrorToast(); - setBanners(bannersFirebase); - }, []); - - function sortProducts(product: Product, productCompare: Product): number { - return productCompare.createdAt - product.createdAt; - } - - const fetchFirebase = useCallback(async () => { - await handleGetBanners(); - await handleGetHighlights(); - await handleGetAbout(); - - setIsLoaded(true); - }, [handleGetAbout, handleGetHighlights, handleGetBanners]); - - useEffect(() => { - fetchFirebase(); - }, [fetchFirebase]); - - useEffect(() => { - const categoriesRef = ref(database, 'categories'); + setBanners(bannersFirebase); + }); - const unsubscribe = onValue(categoriesRef, categoriesSnapshot => { - if (!categoriesSnapshot.val()) { + const unsubscribeCategories = onValue(categoriesRef, categoriesSnapshot => { + if (!categoriesSnapshot.exists()) { setProducts([]); setCategories([]); return; @@ -134,11 +78,53 @@ export function UserProvider({ children }: Required) { setCategories(categoriesMapped); }); + const unsubscribeHighlights = onValue(highlightsRef, highlightsSnapshot => { + if (!highlightsSnapshot.exists()) { + setHighlights([]); + return handleGenericErrorToast(); + } + + const highlightsFirebase = mapper(highlightsSnapshot); + if (!highlightsFirebase) return handleGenericErrorToast(); + + highlightsFirebase.forEach(async highlight => { + if (isGreaterThanPeriodRemove(highlight)) { + const highlightRef = ref(database, `highlights/${highlight.id}`); + remove(highlightRef); + } + }); + + const highlightsInPeriod = highlightsFirebase.filter( + highlight => !isGreaterThanPeriodRemove(highlight), + ); + + setHighlights(highlightsInPeriod); + }); + + const unsubscribeAbout = onValue(aboutRef, aboutSnapshot => { + if (!aboutSnapshot.exists()) return handleGenericErrorToast(); + + const aboutFirebase = mapper(aboutSnapshot)[0]; + if (!aboutFirebase) { + setAbout({} as About); + return handleGenericErrorToast(); + } + + setAbout(aboutFirebase); + }); + () => { - unsubscribe(); + unsubscribeBanners(); + unsubscribeCategories(); + unsubscribeHighlights(); + unsubscribeAbout(); }; }, []); + useEffect(() => { + if (banners.length > 0 && about?.id) setIsLoaded(true); + }, [banners, about]); + return ( Date: Wed, 3 Jul 2024 19:08:24 -0300 Subject: [PATCH 03/23] perf: improve search product by name in `handleSearchProducts` --- src/pages/Products/index.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/pages/Products/index.tsx b/src/pages/Products/index.tsx index 938213d..f77ecda 100644 --- a/src/pages/Products/index.tsx +++ b/src/pages/Products/index.tsx @@ -34,10 +34,10 @@ export function Products() { const productsSelected = searchValue.trim() ? allProductsOfTheCategory.filter(product => - searchValue + product.name .trim() .toLowerCase() - .includes(product.name.trim().toLowerCase()), + .includes(searchValue.trim().toLowerCase()), ) : allProductsOfTheCategory; @@ -51,11 +51,6 @@ export function Products() { setCategorySelected(categories.find(({ id }) => id === category.id)!); } - useEffect(() => { - if (productsFirebase.length) setProducts(productsFirebase); - else setProducts([]); - }, [productsFirebase]); - useEffect(() => { if (!searchValue) handleSearchProducts(); }, [searchValue, productsFirebase, handleSearchProducts]); From 44d2084ae44fcef1542780893e53ff27ee682ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sans=C3=A3o=20Araldi?= Date: Wed, 3 Jul 2024 20:25:27 -0300 Subject: [PATCH 04/23] feat: add `meta` tags to show platform preview --- index.html | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/index.html b/index.html index b6c1b0b..4001b85 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ + @@ -13,6 +14,45 @@ rel="stylesheet" /> + + + + + + + + + + + + + + + + + + + + + + + + Artelier Maisa From 5ecc7cfde03a9ac3b78ca2c41bded166d9238664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sans=C3=A3o=20Araldi?= Date: Fri, 5 Jul 2024 20:05:02 -0300 Subject: [PATCH 05/23] feat: add internationalization libraries and implementation --- package-lock.json | 70 ++++++++++++++++++++++++++++ package.json | 3 ++ src/@types/components/Translator.ts | 3 ++ src/@types/components/index.ts | 1 + src/components/SearchInput/index.tsx | 14 ++++-- src/components/Translator/index.tsx | 14 ++++++ src/components/index.ts | 2 + src/i18n/index.ts | 15 ++++++ src/i18n/locales/en-us.ts | 7 +++ src/i18n/locales/index.ts | 2 + src/i18n/locales/pt-br.ts | 7 +++ src/main.tsx | 1 + src/pages/LandingPage/index.tsx | 19 ++++---- src/pages/NotFound/index.tsx | 7 ++- src/pages/Products/index.tsx | 26 +++++++---- 15 files changed, 169 insertions(+), 22 deletions(-) create mode 100644 src/@types/components/Translator.ts create mode 100644 src/components/Translator/index.tsx create mode 100644 src/i18n/index.ts create mode 100644 src/i18n/locales/en-us.ts create mode 100644 src/i18n/locales/index.ts create mode 100644 src/i18n/locales/pt-br.ts diff --git a/package-lock.json b/package-lock.json index 5430933..1afb084 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,11 @@ "firebase": "^10.11.1", "flowbite": "^2.3.0", "flowbite-react": "^0.9.0", + "i18next": "^23.11.5", + "i18next-browser-languagedetector": "^8.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-i18next": "^14.1.2", "react-modal": "^3.16.1", "react-router-dom": "^6.23.1", "react-scroll": "^1.9.0", @@ -5868,6 +5871,14 @@ "node": "14 || >=16.14" } }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "dependencies": { + "void-elements": "3.1.0" + } + }, "node_modules/http-parser-js": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", @@ -5923,6 +5934,36 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/i18next": { + "version": "23.11.5", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.5.tgz", + "integrity": "sha512-41pvpVbW9rhZPk5xjCX2TPJi2861LEig/YRhUkY+1FQ2IQPS0bKUDYnEqY8XPPbB48h1uIwLnP9iiEfuSl20CA==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz", + "integrity": "sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw==", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/idb": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", @@ -10949,6 +10990,27 @@ "react": "^18.3.1" } }, + "node_modules/react-i18next": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.2.tgz", + "integrity": "sha512-FSIcJy6oauJbGEXfhUgVeLzvWBhIBIS+/9c6Lj4niwKZyGaGb4V4vUbATXSlsHJDXXB+ociNxqFNiFuV1gmoqg==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 23.2.3", + "react": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/react-icons": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.0.1.tgz", @@ -12810,6 +12872,14 @@ } } }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/warning": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", diff --git a/package.json b/package.json index 98c460f..b6a98c3 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,11 @@ "firebase": "^10.11.1", "flowbite": "^2.3.0", "flowbite-react": "^0.9.0", + "i18next": "^23.11.5", + "i18next-browser-languagedetector": "^8.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-i18next": "^14.1.2", "react-modal": "^3.16.1", "react-router-dom": "^6.23.1", "react-scroll": "^1.9.0", diff --git a/src/@types/components/Translator.ts b/src/@types/components/Translator.ts new file mode 100644 index 0000000..aa2600b --- /dev/null +++ b/src/@types/components/Translator.ts @@ -0,0 +1,3 @@ +export interface TranslatorProps { + path: string; +} diff --git a/src/@types/components/index.ts b/src/@types/components/index.ts index 9322e74..cde66ce 100644 --- a/src/@types/components/index.ts +++ b/src/@types/components/index.ts @@ -10,4 +10,5 @@ export * from './ProductCard'; export * from './SearchInput'; export * from './Spinner'; export * from './Text'; +export * from './Translator'; export * from './WhatsAppButton'; diff --git a/src/components/SearchInput/index.tsx b/src/components/SearchInput/index.tsx index 47a6cc9..91fdf86 100644 --- a/src/components/SearchInput/index.tsx +++ b/src/components/SearchInput/index.tsx @@ -1,4 +1,4 @@ -import { memo, useState } from 'react'; +import { FormEvent, memo, useState } from 'react'; import { SearchInputCategoryProps, SearchInputProps } from '../../@types'; import { GenericButton, Icon, Text } from '../'; @@ -16,6 +16,12 @@ function SearchInput(props: SearchInputProps) { setShowDropdown(false); } + function onSubmit(event: FormEvent): void { + event.preventDefault(); + + if (onSearch) onSearch(); + } + const renderCategoryDropdown: React.JSX.Element = (
@@ -63,7 +69,11 @@ function SearchInput(props: SearchInputProps) { onClick={() => setShowDropdown(!showDropdown)} > - {categorySelected ? categorySelected.name : 'Categorias'} + {categorySelected ? ( + categorySelected.name + ) : ( + + )} @@ -78,7 +88,7 @@ function SearchInput(props: SearchInputProps) { value={searchValue} type='search' className='block w-full h-16 z-20 p-4 sm:p-2 sm:pr-16 rounded-lg sm:rounded-none bg-background-color text-primary font-normal text-base border-none placeholder-primary60 focus:outline-none focus:ring-0 focus:border-none' - placeholder='Buscar Produto' + placeholder={t('searchInput.inputPlaceholder')} onChange={onChange} /> @@ -89,7 +99,9 @@ function SearchInput(props: SearchInputProps) { > - Search + + +
@@ -97,14 +109,22 @@ function SearchInput(props: SearchInputProps) {
setShowDropdown(!showDropdown)} isHugWidth /> {showDropdown && renderCategoryDropdown} - +
); diff --git a/src/i18n/locales/en-us.ts b/src/i18n/locales/en-us.ts index 3dd5f88..0c1bad5 100644 --- a/src/i18n/locales/en-us.ts +++ b/src/i18n/locales/en-us.ts @@ -6,7 +6,7 @@ export const enUs = { }, products: { - noProductsAvailable: 'There are no products available', + withoutProductsAvailable: 'There are no products available', loading: 'Preparing our pretty products for you...', }, @@ -50,6 +50,14 @@ export const enUs = { by: 'By', }, + searchInput: { + withoutCategory: 'Without Category', + categoryLabel: 'Categories', + inputPlaceholder: 'Search Product', + buttonLabel: 'Search', + buttonTitle: 'Search', + }, + spinner: { loading: 'Loading...', }, diff --git a/src/i18n/locales/pt-br.ts b/src/i18n/locales/pt-br.ts index 7ddd19c..2f279fb 100644 --- a/src/i18n/locales/pt-br.ts +++ b/src/i18n/locales/pt-br.ts @@ -6,7 +6,7 @@ export const ptBr = { }, products: { - noProductsAvailable: 'Não há produtos disponíveis', + withoutProductsAvailable: 'Não há produtos disponíveis', loading: 'Preparando nossos lindos produtos para você...', }, @@ -50,6 +50,14 @@ export const ptBr = { by: 'Por', }, + searchInput: { + withoutCategory: 'Sem Categoria', + categoryLabel: 'Categorias', + inputPlaceholder: 'Buscar Produto', + buttonLabel: 'Pesquisar', + buttonTitle: 'Pesquisar', + }, + spinner: { loading: 'Carregando...', }, diff --git a/src/pages/Products/index.tsx b/src/pages/Products/index.tsx index 6e1cb7e..cda76d0 100644 --- a/src/pages/Products/index.tsx +++ b/src/pages/Products/index.tsx @@ -99,7 +99,7 @@ export function Products() { ) : (
- + From 7d5406cc47a24242c1f5258f4b181e8890c8621f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sans=C3=A3o=20Araldi?= Date: Fri, 5 Jul 2024 22:24:06 -0300 Subject: [PATCH 18/23] feat: add internationalization label that's faulted to the `LandingPage` --- src/i18n/locales/en-us.ts | 1 + src/i18n/locales/pt-br.ts | 1 + src/pages/LandingPage/index.tsx | 6 ++++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/i18n/locales/en-us.ts b/src/i18n/locales/en-us.ts index 0c1bad5..f583982 100644 --- a/src/i18n/locales/en-us.ts +++ b/src/i18n/locales/en-us.ts @@ -3,6 +3,7 @@ export const enUs = { landingPage: { aboutTitle: 'About the Maisa', loading: 'Preparing special something for you...', + ourProducts: 'Met Our Products', }, products: { diff --git a/src/i18n/locales/pt-br.ts b/src/i18n/locales/pt-br.ts index 2f279fb..77bb0e7 100644 --- a/src/i18n/locales/pt-br.ts +++ b/src/i18n/locales/pt-br.ts @@ -3,6 +3,7 @@ export const ptBr = { landingPage: { aboutTitle: 'Sobre a Maisa', loading: 'Preparando algo especial para você...', + ourProducts: 'Conheça Nossos Produtos', }, products: { diff --git a/src/pages/LandingPage/index.tsx b/src/pages/LandingPage/index.tsx index 61550e4..9658cd4 100644 --- a/src/pages/LandingPage/index.tsx +++ b/src/pages/LandingPage/index.tsx @@ -1,4 +1,5 @@ import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import { Element } from 'react-scroll'; @@ -22,6 +23,7 @@ export function LandingPage() { const [productSelected, setProductSelected] = useState(null); const { about, highlights, banners, products, isLoaded } = useUser(); + const { t } = useTranslation(); const navigate = useNavigate(); function navigateToProductsPage(): void { @@ -71,7 +73,7 @@ export function LandingPage() {
@@ -103,7 +105,7 @@ export function LandingPage() {
{`Foto From ca1b22416b3026d85d77776181fb0846f82999d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sans=C3=A3o=20Araldi?= Date: Sun, 7 Jul 2024 13:45:51 -0300 Subject: [PATCH 19/23] refactor: change `sendMessage` for `buildWhatsAppUrl` to it only makes build url --- src/@types/utils/whatsapp.ts | 8 +++----- src/components/Footer/index.tsx | 9 +++++++-- src/components/WhatsAppButton/index.tsx | 9 +++++++-- src/pages/LandingPage/index.tsx | 2 +- src/utils/whatsapp.ts | 16 ++++------------ 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/@types/utils/whatsapp.ts b/src/@types/utils/whatsapp.ts index 9712e32..53fef69 100644 --- a/src/@types/utils/whatsapp.ts +++ b/src/@types/utils/whatsapp.ts @@ -1,6 +1,4 @@ -import { WhatsAppButtonProps } from '../components'; - -export type SendMessageType = 'footer' | 'whatsapp-button'; -export interface SendMessageProps extends Partial { - type?: SendMessageType; +export interface BuildWhatsAppUrlProps { + message: string; + phone?: string; } diff --git a/src/components/Footer/index.tsx b/src/components/Footer/index.tsx index f3d4075..5d1ff39 100644 --- a/src/components/Footer/index.tsx +++ b/src/components/Footer/index.tsx @@ -4,7 +4,7 @@ import { memo } from 'react'; import packageJson from '../../../package.json'; import { IconProps } from '../../@types'; import { DEFAULT_EMAIL } from '../../config'; -import { sendMessage } from '../../utils'; +import { buildWhatsAppUrl } from '../../utils'; import { Icon, Text } from '../'; function Footer() { @@ -17,7 +17,12 @@ function Footer() { }; function onSendWhatsAppMessage(): void { - window.open(sendMessage({ type: 'footer' })); + window.open( + buildWhatsAppUrl({ + message: + 'Olá, estava olhando o seu site e resolvi entrar em contato. Tenho interesse em seus produtos!', + }), + ); } return ( diff --git a/src/components/WhatsAppButton/index.tsx b/src/components/WhatsAppButton/index.tsx index 3ad9653..595e31d 100644 --- a/src/components/WhatsAppButton/index.tsx +++ b/src/components/WhatsAppButton/index.tsx @@ -2,14 +2,19 @@ import { memo } from 'react'; import { WhatsAppButtonProps } from '../../@types'; import { DEFAULT_PHONE } from '../../config'; -import { sendMessage } from '../../utils'; +import { buildWhatsAppUrl } from '../../utils'; import { Icon, Text } from '../'; function WhatsAppButton(props: WhatsAppButtonProps) { const { product, phone = DEFAULT_PHONE } = props; function onSendWhatsAppMessage(): void { - window.open(sendMessage({ phone, product })); + window.open( + buildWhatsAppUrl({ + phone, + message: `Olá, estou interresado(a) no produto "${product}" que achei no seu site, gostaria de conversar sobre ele.`, + }), + ); } return ( diff --git a/src/pages/LandingPage/index.tsx b/src/pages/LandingPage/index.tsx index 9658cd4..65a2cdc 100644 --- a/src/pages/LandingPage/index.tsx +++ b/src/pages/LandingPage/index.tsx @@ -73,7 +73,7 @@ export function LandingPage() {
diff --git a/src/utils/whatsapp.ts b/src/utils/whatsapp.ts index f8505bf..999dbff 100644 --- a/src/utils/whatsapp.ts +++ b/src/utils/whatsapp.ts @@ -1,16 +1,8 @@ -import { SendMessageProps } from '../@types'; +import { BuildWhatsAppUrlProps } from '../@types'; import { DEFAULT_PHONE } from '../config'; -export function sendMessage(props: SendMessageProps) { - const { type = 'whatsapp-button', phone = DEFAULT_PHONE, product } = props; +export function buildWhatsAppUrl(props: BuildWhatsAppUrlProps) { + const { message, phone = DEFAULT_PHONE } = props; - const productName = product ? `"${product}" ` : ''; - - const messages: Record['type'], string> = { - footer: - 'Olá, estava olhando o seu site e resolvi entrar em contato. Tenho interesse em seus produtos!', - 'whatsapp-button': `Olá, estou interresado(a) no produto ${productName}que achei no seu site, gostaria de conversar sobre ele.`, - }; - - return `https://wa.me/${phone}?text=${encodeURIComponent(messages[type])}`; + return `https://wa.me/${phone}?text=${encodeURIComponent(message)}`; } From a56dee22f8849d27fd1cf00b8742fcf82df6e1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sans=C3=A3o=20Araldi?= Date: Sun, 7 Jul 2024 14:23:04 -0300 Subject: [PATCH 20/23] feat: add internationalization to `Footer` component --- src/components/Footer/index.tsx | 35 ++++++++++++++++++++------------- src/i18n/locales/en-us.ts | 18 +++++++++++++++++ src/i18n/locales/pt-br.ts | 18 +++++++++++++++++ 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/src/components/Footer/index.tsx b/src/components/Footer/index.tsx index 5d1ff39..8f39ce7 100644 --- a/src/components/Footer/index.tsx +++ b/src/components/Footer/index.tsx @@ -1,13 +1,16 @@ import { Footer as FlowbiteFooter } from 'flowbite-react'; import { memo } from 'react'; +import { useTranslation } from 'react-i18next'; import packageJson from '../../../package.json'; import { IconProps } from '../../@types'; import { DEFAULT_EMAIL } from '../../config'; import { buildWhatsAppUrl } from '../../utils'; -import { Icon, Text } from '../'; +import { Icon, Text, Translator } from '../'; function Footer() { + const { t } = useTranslation(); + const version = packageJson.version; const currentYear = new Date().getFullYear(); @@ -17,39 +20,39 @@ function Footer() { }; function onSendWhatsAppMessage(): void { - window.open( - buildWhatsAppUrl({ - message: - 'Olá, estava olhando o seu site e resolvi entrar em contato. Tenho interesse em seus produtos!', - }), - ); + window.open(buildWhatsAppUrl({ message: t('footer.whatsAppMessage') })); } return (
- Todos os Direitos Reservados. + + + - Versão {version}. + + {version}. +
- Projeto de extensão desenvolvido na{' '} + {' '} - Univali + @@ -61,6 +64,7 @@ function Footer() { className='rounded focus:outline-none focus:ring focus:ring-facebook focus:border-facebook' href='https://www.facebook.com/artelier.maisa/' target='_blank' + title={t('footer.facebook')} > @@ -81,6 +86,7 @@ function Footer() { type='button' className='rounded focus:outline-none focus:ring focus:ring-whatsapp focus:border-whatring-whatsapp' onClick={onSendWhatsAppMessage} + title={t('footer.whatsapp')} > Date: Sun, 7 Jul 2024 14:26:11 -0300 Subject: [PATCH 21/23] fix: add title to change language buttons --- src/components/Header/index.tsx | 2 ++ src/i18n/locales/en-us.ts | 2 ++ src/i18n/locales/pt-br.ts | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index a034547..5c7da5d 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -87,6 +87,7 @@ function Header() {
- handleTo(null)}> + handleTo(null)}>