From 9d8cee4dcdcc70a04dfd74328daabafa0f0ea4a2 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Thu, 26 Dec 2024 13:26:39 -0300 Subject: [PATCH 01/26] merge --- apps/web-mobile/index.html | 32 ++++++++++--------- .../src/components/captcha/index.tsx | 31 ++++++++++++++++++ .../src/components/captcha/types.ts | 12 +++++++ .../src/modules/home/screens/main/index.tsx | 1 + 4 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 apps/web-mobile/src/components/captcha/index.tsx create mode 100644 apps/web-mobile/src/components/captcha/types.ts diff --git a/apps/web-mobile/index.html b/apps/web-mobile/index.html index dc1bfd3f..3cfd9a36 100644 --- a/apps/web-mobile/index.html +++ b/apps/web-mobile/index.html @@ -1,18 +1,20 @@ - - - - - - Recy - App - - -
- - + + + + + + + Recy - App + + + + +
+ + + diff --git a/apps/web-mobile/src/components/captcha/index.tsx b/apps/web-mobile/src/components/captcha/index.tsx new file mode 100644 index 00000000..f35c8f1a --- /dev/null +++ b/apps/web-mobile/src/components/captcha/index.tsx @@ -0,0 +1,31 @@ +import { useEffect } from 'react'; +import { turnstileWindow } from './types'; + +const SCRIPT_CAPTCHA = ( + +); +const SITE_KEY = '0x4AAAAAAA1xm1WGL4XXa0S0'; +const { turnstile }: turnstileWindow = window; + +const captchaTrigger = async () => { + try { + turnstile.remove(); + turnstile.render('.cf-turnstile', { + sitekey: SITE_KEY, + appearance: 'interaction-only', + callback: (token) => { + console.log('challenge: ', token); + }, + }); + } catch (err) { + console.log(err); + } +}; +const Captcha = () => { + useEffect(() => { + captchaTrigger(); + }, []); + return
; +}; + +export default Captcha; diff --git a/apps/web-mobile/src/components/captcha/types.ts b/apps/web-mobile/src/components/captcha/types.ts new file mode 100644 index 00000000..301b9b54 --- /dev/null +++ b/apps/web-mobile/src/components/captcha/types.ts @@ -0,0 +1,12 @@ +export type turnstileWindow = Window & { + turnstile?: { + remove: (string?: string) => void; + render: (string: string, { sitekey, callback }: turnstileRenderBody) => void; + getResponse: () => void; + }; +}; +type turnstileRenderBody = { + sitekey: string; + callback: (token: any) => void; + appearance: string; +}; diff --git a/apps/web-mobile/src/modules/home/screens/main/index.tsx b/apps/web-mobile/src/modules/home/screens/main/index.tsx index 1a5da1da..9043dc8e 100644 --- a/apps/web-mobile/src/modules/home/screens/main/index.tsx +++ b/apps/web-mobile/src/modules/home/screens/main/index.tsx @@ -6,6 +6,7 @@ import { Suspense } from 'react'; import { useTranslation } from 'react-i18next'; import LocaleToggler from '@/components/locale-toggler'; import { Button } from '@/components/ui/button'; +import Captcha from '@/components/captcha'; import { Loader2 } from 'lucide-react'; import { validateAuthProvider } from '@/utils/auth'; From ca9ff5afe0e370c890335eb3782daafa7949acf3 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Fri, 13 Dec 2024 01:44:56 -0300 Subject: [PATCH 02/26] feat: add verification with server side --- .../src/components/captcha/index.tsx | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/apps/web-mobile/src/components/captcha/index.tsx b/apps/web-mobile/src/components/captcha/index.tsx index f35c8f1a..9285b050 100644 --- a/apps/web-mobile/src/components/captcha/index.tsx +++ b/apps/web-mobile/src/components/captcha/index.tsx @@ -1,26 +1,47 @@ import { useEffect } from 'react'; import { turnstileWindow } from './types'; +import { api } from '@/libs/axios'; +import { toast } from '../ui/use-toast'; -const SCRIPT_CAPTCHA = ( - -); const SITE_KEY = '0x4AAAAAAA1xm1WGL4XXa0S0'; const { turnstile }: turnstileWindow = window; -const captchaTrigger = async () => { +const captchaTrigger = () => { try { - turnstile.remove(); turnstile.render('.cf-turnstile', { sitekey: SITE_KEY, appearance: 'interaction-only', - callback: (token) => { - console.log('challenge: ', token); + callback: async (token) => { + await verifyCatpcha(token); }, }); - } catch (err) { - console.log(err); + } catch (error) { + if (error instanceof Error) { + toast({ + title: error.message, + variant: 'destructive', + }); + } } }; + +const verifyCatpcha = async (token: string) => { + const BASE_URL = import.meta.env.VITE_AWS_LAMBDA; + const ENVIRONMENT = import.meta.env.PROD ? 'production' : 'staging'; + const ENDPOINT = `${BASE_URL}/${ENVIRONMENT}/v1/captcha`; + + try { + await api.post(ENDPOINT, { token }); + } catch (error) { + if (error instanceof Error) { + toast({ + title: error.message, + variant: 'destructive', + }); + } + } +}; + const Captcha = () => { useEffect(() => { captchaTrigger(); From 76724a9be1a130b2201f5599fe58ddaf238c40f5 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Fri, 13 Dec 2024 19:48:45 -0300 Subject: [PATCH 03/26] refactor: improvment on types --- apps/web-mobile/src/components/captcha/types.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/web-mobile/src/components/captcha/types.ts b/apps/web-mobile/src/components/captcha/types.ts index 301b9b54..8b0957a2 100644 --- a/apps/web-mobile/src/components/captcha/types.ts +++ b/apps/web-mobile/src/components/captcha/types.ts @@ -1,12 +1,15 @@ export type turnstileWindow = Window & { turnstile?: { remove: (string?: string) => void; - render: (string: string, { sitekey, callback }: turnstileRenderBody) => void; + render: (string: string, options: turnstileRenderBody) => void; getResponse: () => void; }; }; type turnstileRenderBody = { sitekey: string; - callback: (token: any) => void; + callback: (token: string) => void; appearance: string; + language?: string; + theme?: 'light' | 'dark' | 'auto'; + size?: 'normal' | 'compact'; }; From 37da34112b3b71b789faf686258091a19ec6cb27 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Fri, 13 Dec 2024 20:28:08 -0300 Subject: [PATCH 04/26] Refactor: structure captcha --- .../src/components/captcha/index.tsx | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/apps/web-mobile/src/components/captcha/index.tsx b/apps/web-mobile/src/components/captcha/index.tsx index 9285b050..bda42b58 100644 --- a/apps/web-mobile/src/components/captcha/index.tsx +++ b/apps/web-mobile/src/components/captcha/index.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useEffect, useRef } from 'react'; import { turnstileWindow } from './types'; import { api } from '@/libs/axios'; import { toast } from '../ui/use-toast'; @@ -6,45 +6,52 @@ import { toast } from '../ui/use-toast'; const SITE_KEY = '0x4AAAAAAA1xm1WGL4XXa0S0'; const { turnstile }: turnstileWindow = window; -const captchaTrigger = () => { - try { - turnstile.render('.cf-turnstile', { - sitekey: SITE_KEY, - appearance: 'interaction-only', - callback: async (token) => { - await verifyCatpcha(token); - }, - }); - } catch (error) { - if (error instanceof Error) { - toast({ - title: error.message, - variant: 'destructive', - }); - } - } -}; - const verifyCatpcha = async (token: string) => { const BASE_URL = import.meta.env.VITE_AWS_LAMBDA; const ENVIRONMENT = import.meta.env.PROD ? 'production' : 'staging'; const ENDPOINT = `${BASE_URL}/${ENVIRONMENT}/v1/captcha`; try { - await api.post(ENDPOINT, { token }); + const { data } = await api.post(ENDPOINT, { token }); + + if (!data.success) throw new Error('Captcha verification failed'); } catch (error) { if (error instanceof Error) { toast({ title: error.message, variant: 'destructive', }); + throw error; } } }; const Captcha = () => { + const widgetIdRef = useRef(); + useEffect(() => { - captchaTrigger(); + try { + if (!turnstile) throw new Error('Turnstile not initialized'); + + widgetIdRef.current = turnstile.render('.cf-turnstile', { + sitekey: SITE_KEY, + appearance: 'interaction-only', + callback: async (token) => { + await verifyCatpcha(token); + }, + }); + } catch (error) { + if (error instanceof Error) { + toast({ + title: error.message, + description: 'Please refresh the page or try again later', + variant: 'destructive', + }); + } + } + return () => { + if (turnstile && widgetIdRef.current) turnstile.remove(widgetIdRef.current); + }; }, []); return
; }; From fa8505c2270402b617db0d431aded546815fa704 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Thu, 26 Dec 2024 13:27:54 -0300 Subject: [PATCH 05/26] merge --- apps/web-mobile/index.html | 2 - .../src/components/captcha/index.tsx | 59 ------------------- .../src/components/captcha/types.ts | 15 ----- .../src/modules/home/screens/main/index.tsx | 1 - .../components/profile/profile-form/index.tsx | 14 ++--- package.json | 1 + pnpm-lock.yaml | 14 +++++ 7 files changed, 21 insertions(+), 85 deletions(-) delete mode 100644 apps/web-mobile/src/components/captcha/index.tsx delete mode 100644 apps/web-mobile/src/components/captcha/types.ts diff --git a/apps/web-mobile/index.html b/apps/web-mobile/index.html index 3cfd9a36..7259251e 100644 --- a/apps/web-mobile/index.html +++ b/apps/web-mobile/index.html @@ -8,8 +8,6 @@ Recy - App - diff --git a/apps/web-mobile/src/components/captcha/index.tsx b/apps/web-mobile/src/components/captcha/index.tsx deleted file mode 100644 index bda42b58..00000000 --- a/apps/web-mobile/src/components/captcha/index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { useEffect, useRef } from 'react'; -import { turnstileWindow } from './types'; -import { api } from '@/libs/axios'; -import { toast } from '../ui/use-toast'; - -const SITE_KEY = '0x4AAAAAAA1xm1WGL4XXa0S0'; -const { turnstile }: turnstileWindow = window; - -const verifyCatpcha = async (token: string) => { - const BASE_URL = import.meta.env.VITE_AWS_LAMBDA; - const ENVIRONMENT = import.meta.env.PROD ? 'production' : 'staging'; - const ENDPOINT = `${BASE_URL}/${ENVIRONMENT}/v1/captcha`; - - try { - const { data } = await api.post(ENDPOINT, { token }); - - if (!data.success) throw new Error('Captcha verification failed'); - } catch (error) { - if (error instanceof Error) { - toast({ - title: error.message, - variant: 'destructive', - }); - throw error; - } - } -}; - -const Captcha = () => { - const widgetIdRef = useRef(); - - useEffect(() => { - try { - if (!turnstile) throw new Error('Turnstile not initialized'); - - widgetIdRef.current = turnstile.render('.cf-turnstile', { - sitekey: SITE_KEY, - appearance: 'interaction-only', - callback: async (token) => { - await verifyCatpcha(token); - }, - }); - } catch (error) { - if (error instanceof Error) { - toast({ - title: error.message, - description: 'Please refresh the page or try again later', - variant: 'destructive', - }); - } - } - return () => { - if (turnstile && widgetIdRef.current) turnstile.remove(widgetIdRef.current); - }; - }, []); - return
; -}; - -export default Captcha; diff --git a/apps/web-mobile/src/components/captcha/types.ts b/apps/web-mobile/src/components/captcha/types.ts deleted file mode 100644 index 8b0957a2..00000000 --- a/apps/web-mobile/src/components/captcha/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type turnstileWindow = Window & { - turnstile?: { - remove: (string?: string) => void; - render: (string: string, options: turnstileRenderBody) => void; - getResponse: () => void; - }; -}; -type turnstileRenderBody = { - sitekey: string; - callback: (token: string) => void; - appearance: string; - language?: string; - theme?: 'light' | 'dark' | 'auto'; - size?: 'normal' | 'compact'; -}; diff --git a/apps/web-mobile/src/modules/home/screens/main/index.tsx b/apps/web-mobile/src/modules/home/screens/main/index.tsx index 9043dc8e..1a5da1da 100644 --- a/apps/web-mobile/src/modules/home/screens/main/index.tsx +++ b/apps/web-mobile/src/modules/home/screens/main/index.tsx @@ -6,7 +6,6 @@ import { Suspense } from 'react'; import { useTranslation } from 'react-i18next'; import LocaleToggler from '@/components/locale-toggler'; import { Button } from '@/components/ui/button'; -import Captcha from '@/components/captcha'; import { Loader2 } from 'lucide-react'; import { validateAuthProvider } from '@/utils/auth'; diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index 24607487..e460accb 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -5,19 +5,14 @@ import { z } from 'zod'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { Button } from '@/components/ui/button'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@/components/ui/form'; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { Separator } from '@/components/ui/separator'; import { toast } from '@/components/ui/use-toast'; +import { Turnstile } from '@marsidev/react-turnstile'; +import { useState } from 'react'; const profileFormSchema = z.object({ email: z @@ -44,6 +39,8 @@ type ProfileFormValues = z.infer; export default function ProfileForm() { const { user } = useAuth0(); + const [turnstileToken, setTurnstileToken] = useState(); + const form = useForm({ // defaultValues, mode: 'onChange', @@ -145,6 +142,7 @@ export default function ProfileForm() { + diff --git a/package.json b/package.json index cd1b89b0..faead9e7 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "@eslint/js": "^9.0.0", "@hookform/resolvers": "^3.9.1", "@iconify/react": "^4.1.1", + "@marsidev/react-turnstile": "^1.1.0", "@nestjs/common": "^10.0.2", "@nestjs/core": "^10.0.2", "@nestjs/platform-express": "^10.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 052288e5..36fb574f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: '@iconify/react': specifier: ^4.1.1 version: 4.1.1(react@18.3.1) + '@marsidev/react-turnstile': + specifier: ^1.1.0 + version: 1.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@nestjs/common': specifier: ^10.0.2 version: 10.4.8(reflect-metadata@0.1.14)(rxjs@7.8.1) @@ -1887,6 +1890,12 @@ packages: resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} engines: {node: '>=8'} + '@marsidev/react-turnstile@1.1.0': + resolution: {integrity: sha512-X7bP9ZYutDd+E+klPYF+/BJHqEyyVkN4KKmZcNRr84zs3DcMoftlMAuoKqNSnqg0HE7NQ1844+TLFSJoztCdSA==} + peerDependencies: + react: ^17.0.2 || ^18.0.0 || ^19.0 + react-dom: ^17.0.2 || ^18.0.0 || ^19.0 + '@metamask/eth-json-rpc-provider@1.0.1': resolution: {integrity: sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA==} engines: {node: '>=14.0.0'} @@ -13824,6 +13833,11 @@ snapshots: '@lukeed/csprng@1.1.0': {} + '@marsidev/react-turnstile@1.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + '@metamask/eth-json-rpc-provider@1.0.1': dependencies: '@metamask/json-rpc-engine': 7.3.3 From de4e4165758a4fa56a22b0a23f5fa27b8385b626 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Fri, 27 Dec 2024 21:16:06 -0300 Subject: [PATCH 06/26] Style: improvement style on profile settings --- .../components/profile/profile-form/index.tsx | 20 ++++++++++++------- .../settings/screens/profile/index.tsx | 4 ++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index e460accb..c549c3c1 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -60,9 +60,9 @@ export default function ProfileForm() { return (
- +
-

Basic Info

+

Basic Info:

@@ -73,7 +73,10 @@ export default function ProfileForm() { name="preferred_name" render={({ field }) => ( - Preferred Name + + Preferred Name + * + @@ -87,7 +90,10 @@ export default function ProfileForm() { name="phone" render={({ field }) => ( - Phone number + + Phone number + * + @@ -101,7 +107,7 @@ export default function ProfileForm() { control={form.control} name="email" render={({ field }) => ( - + Email @@ -114,7 +120,7 @@ export default function ProfileForm() { @@ -123,7 +129,7 @@ export default function ProfileForm() {
-

Profile Type

+

Profile Type:

diff --git a/apps/web-mobile/src/modules/settings/screens/profile/index.tsx b/apps/web-mobile/src/modules/settings/screens/profile/index.tsx index f4df2d7c..c6651a40 100644 --- a/apps/web-mobile/src/modules/settings/screens/profile/index.tsx +++ b/apps/web-mobile/src/modules/settings/screens/profile/index.tsx @@ -4,8 +4,8 @@ import ProfileForm from '@/modules/settings/components/profile/profile-form'; export default function SettingsMainScreen() { return ( -
-

Profile settings

+
+

Profile settings

); From 97f08c480d6925c45bfdd51176b0cecb014daee5 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Mon, 30 Dec 2024 12:47:20 -0300 Subject: [PATCH 07/26] Feature: add radioBox component --- .../web-mobile/src/components/ui/radioBox.tsx | 30 +++++++++++++++ .../components/profile/profile-form/index.tsx | 38 ++++++++++++------- 2 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 apps/web-mobile/src/components/ui/radioBox.tsx diff --git a/apps/web-mobile/src/components/ui/radioBox.tsx b/apps/web-mobile/src/components/ui/radioBox.tsx new file mode 100644 index 00000000..1f7d14e8 --- /dev/null +++ b/apps/web-mobile/src/components/ui/radioBox.tsx @@ -0,0 +1,30 @@ +import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; +import { Label } from '@/components/ui/label'; + +const cssmap: any = { + 'option-hodler': 'option-hodler', + 'option-recycler': 'option-recycler', + 'option-waste': 'option-waste', +}; +interface Props { + beforeText?: string; + id: string; + name: string; + activeState: (string: string) => void; +} +export const RadioBox = ({ beforeText, id, name, activeState }: Props) => { + return ( +
#${cssmap[id]}]:hidden`} + > + activeState(`${id}-box`)} /> +
+ {beforeText && {beforeText}} + +
+
+ ); +}; diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index c549c3c1..fed8c2d3 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -13,6 +13,7 @@ import { Separator } from '@/components/ui/separator'; import { toast } from '@/components/ui/use-toast'; import { Turnstile } from '@marsidev/react-turnstile'; import { useState } from 'react'; +import { RadioBox } from '@/components/ui/radioBox'; const profileFormSchema = z.object({ email: z @@ -37,9 +38,16 @@ const profileFormSchema = z.object({ type ProfileFormValues = z.infer; +const cssmap: any = { + 'option-hodler-box': 'option-hodler-box', + 'option-recycler-box': 'option-recycler-box', + 'option-waste-box': 'option-waste-box', +}; + export default function ProfileForm() { const { user } = useAuth0(); const [turnstileToken, setTurnstileToken] = useState(); + const [radioActive, setRadioActive] = useState(); const form = useForm({ // defaultValues, @@ -133,22 +141,24 @@ export default function ProfileForm() {
- -
- - -
-
- - -
-
- - -
+ #${cssmap[radioActive]}]:border-blue-500`} + data-active={radioActive} + > + + + + + - + {/* */} From bf7341f97b421f4ee639494c5b3b080d503a7ed4 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Mon, 30 Dec 2024 13:03:22 -0300 Subject: [PATCH 08/26] feature: add correct types --- apps/web-mobile/src/components/ui/radioBox.tsx | 5 ++++- .../settings/components/profile/profile-form/index.tsx | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/web-mobile/src/components/ui/radioBox.tsx b/apps/web-mobile/src/components/ui/radioBox.tsx index 1f7d14e8..372f26a1 100644 --- a/apps/web-mobile/src/components/ui/radioBox.tsx +++ b/apps/web-mobile/src/components/ui/radioBox.tsx @@ -1,7 +1,10 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { Label } from '@/components/ui/label'; -const cssmap: any = { +type cssmapType = { + [id: string]: string; +}; +const cssmap: cssmapType = { 'option-hodler': 'option-hodler', 'option-recycler': 'option-recycler', 'option-waste': 'option-waste', diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index fed8c2d3..85ca4325 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -38,7 +38,11 @@ const profileFormSchema = z.object({ type ProfileFormValues = z.infer; -const cssmap: any = { +type cssmapType = { + [id: string]: string; +}; + +const cssmap: cssmapType = { 'option-hodler-box': 'option-hodler-box', 'option-recycler-box': 'option-recycler-box', 'option-waste-box': 'option-waste-box', @@ -158,7 +162,7 @@ export default function ProfileForm() {
- {/* */} + From 9aa51d135104e765d1cc9a255eaedc569be065ba Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Mon, 30 Dec 2024 15:05:25 -0300 Subject: [PATCH 09/26] Feature: add success, focus and error styles on inputs --- apps/web-mobile/src/components/ui/input.tsx | 28 +++++++++---------- .../components/profile/profile-form/index.tsx | 17 +++++++++-- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/apps/web-mobile/src/components/ui/input.tsx b/apps/web-mobile/src/components/ui/input.tsx index 61f5d546..68dff9f4 100644 --- a/apps/web-mobile/src/components/ui/input.tsx +++ b/apps/web-mobile/src/components/ui/input.tsx @@ -4,21 +4,19 @@ import { cn } from '@/utils/cn'; export interface InputProps extends React.InputHTMLAttributes {} -const Input = React.forwardRef( - ({ className, type, ...props }, ref) => { - return ( - - ); - }, -); +const Input = React.forwardRef(({ className, type, ...props }, ref) => { + return ( + + ); +}); Input.displayName = 'Input'; export { Input }; diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index 85ca4325..341a6f0f 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -90,7 +90,10 @@ export default function ProfileForm() { * - +
@@ -107,7 +110,11 @@ export default function ProfileForm() { * - +
@@ -122,7 +129,11 @@ export default function ProfileForm() { Email - + From 6a999764455c1c882d880a2ecae09a1aec5e0dd9 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Mon, 30 Dec 2024 16:45:05 -0300 Subject: [PATCH 10/26] feature: add styles for inputs --- .../components/profile/profile-form/index.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index 341a6f0f..0b56329c 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -79,7 +79,7 @@ export default function ProfileForm() {
-
+
@@ -113,7 +116,8 @@ export default function ProfileForm() { @@ -126,13 +130,14 @@ export default function ProfileForm() { control={form.control} name="email" render={({ field }) => ( - + Email @@ -158,7 +163,7 @@ export default function ProfileForm() { #${cssmap[radioActive]}]:border-blue-500`} + className={`grid grid-cols-6 [&[data-active='${cssmap[radioActive]}']>#${cssmap[radioActive]}]:border-blue-500 max-md:grid-cols-2`} data-active={radioActive} > From b6b4456970faa2998ddf69df09715549a2be746b Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Mon, 30 Dec 2024 17:57:53 -0300 Subject: [PATCH 11/26] feature: styles for radiobox check --- apps/web-mobile/src/components/ui/radioBox.tsx | 5 ++++- .../settings/components/profile/profile-form/index.tsx | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/web-mobile/src/components/ui/radioBox.tsx b/apps/web-mobile/src/components/ui/radioBox.tsx index 372f26a1..cdbc2907 100644 --- a/apps/web-mobile/src/components/ui/radioBox.tsx +++ b/apps/web-mobile/src/components/ui/radioBox.tsx @@ -19,7 +19,7 @@ export const RadioBox = ({ beforeText, id, name, activeState }: Props) => { return (
#${cssmap[id]}]:hidden`} + className={`relative flex items-center space-x-2 rounded-lg border-2 px-4 py-6 [&>#${cssmap[id]}]:hidden`} > activeState(`${id}-box`)} />
@@ -28,6 +28,9 @@ export const RadioBox = ({ beforeText, id, name, activeState }: Props) => { {name}
+ + ✓ +
); }; diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index 0b56329c..93485e74 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -163,7 +163,7 @@ export default function ProfileForm() { #${cssmap[radioActive]}]:border-blue-500 max-md:grid-cols-2`} + className={`grid grid-cols-6 [&[data-active='${cssmap[radioActive]}']>#${cssmap[radioActive]}]:border-blue-500 max-md:grid-cols-2 [&[data-active='${cssmap[radioActive]}']>#${cssmap[radioActive]}>.checked-box-symbol]:block`} data-active={radioActive} > From cb43dc7994dcfe9707172390c1184a2b119a44f7 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Fri, 27 Dec 2024 21:16:06 -0300 Subject: [PATCH 12/26] Style: improvement style on profile settings --- .../components/profile/profile-form/index.tsx | 20 ++++++++++++------- .../settings/screens/profile/index.tsx | 4 ++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index 47cf113f..a0d299ef 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -60,9 +60,9 @@ export default function ProfileForm() { return (
- +
-

Basic Info

+

Basic Info:

@@ -73,7 +73,10 @@ export default function ProfileForm() { name="preferred_name" render={({ field }) => ( - Preferred Name + + Preferred Name + * + @@ -87,7 +90,10 @@ export default function ProfileForm() { name="phone" render={({ field }) => ( - Phone number + + Phone number + * + @@ -101,7 +107,7 @@ export default function ProfileForm() { control={form.control} name="email" render={({ field }) => ( - + Email @@ -114,7 +120,7 @@ export default function ProfileForm() { @@ -123,7 +129,7 @@ export default function ProfileForm() {
-

Profile Type

+

Profile Type:

diff --git a/apps/web-mobile/src/modules/settings/screens/profile/index.tsx b/apps/web-mobile/src/modules/settings/screens/profile/index.tsx index f4df2d7c..c6651a40 100644 --- a/apps/web-mobile/src/modules/settings/screens/profile/index.tsx +++ b/apps/web-mobile/src/modules/settings/screens/profile/index.tsx @@ -4,8 +4,8 @@ import ProfileForm from '@/modules/settings/components/profile/profile-form'; export default function SettingsMainScreen() { return ( -
-

Profile settings

+
+

Profile settings

); From 81adb7558987149851fc9370da8b6435fe578ebd Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Mon, 30 Dec 2024 12:47:20 -0300 Subject: [PATCH 13/26] Feature: add radioBox component --- .../web-mobile/src/components/ui/radioBox.tsx | 30 +++++++++++++++ .../components/profile/profile-form/index.tsx | 38 ++++++++++++------- 2 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 apps/web-mobile/src/components/ui/radioBox.tsx diff --git a/apps/web-mobile/src/components/ui/radioBox.tsx b/apps/web-mobile/src/components/ui/radioBox.tsx new file mode 100644 index 00000000..1f7d14e8 --- /dev/null +++ b/apps/web-mobile/src/components/ui/radioBox.tsx @@ -0,0 +1,30 @@ +import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; +import { Label } from '@/components/ui/label'; + +const cssmap: any = { + 'option-hodler': 'option-hodler', + 'option-recycler': 'option-recycler', + 'option-waste': 'option-waste', +}; +interface Props { + beforeText?: string; + id: string; + name: string; + activeState: (string: string) => void; +} +export const RadioBox = ({ beforeText, id, name, activeState }: Props) => { + return ( +
#${cssmap[id]}]:hidden`} + > + activeState(`${id}-box`)} /> +
+ {beforeText && {beforeText}} + +
+
+ ); +}; diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index a0d299ef..8b30a321 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -13,6 +13,7 @@ import { toast } from '@/components/ui/use-toast'; import { Turnstile } from '@marsidev/react-turnstile'; import { useState } from 'react'; import { useAuth } from '@/hooks/auth'; +import { RadioBox } from '@/components/ui/radioBox'; const profileFormSchema = z.object({ email: z @@ -37,9 +38,16 @@ const profileFormSchema = z.object({ type ProfileFormValues = z.infer; +const cssmap: any = { + 'option-hodler-box': 'option-hodler-box', + 'option-recycler-box': 'option-recycler-box', + 'option-waste-box': 'option-waste-box', +}; + export default function ProfileForm() { const { user } = useAuth(); const [turnstileToken, setTurnstileToken] = useState(); + const [radioActive, setRadioActive] = useState(); const form = useForm({ // defaultValues, @@ -133,22 +141,24 @@ export default function ProfileForm() {
- -
- - -
-
- - -
-
- - -
+ #${cssmap[radioActive]}]:border-blue-500`} + data-active={radioActive} + > + + + + + - + {/* */} From 5d0af9a2fb1bc652b2560426dbe93c1b3d6c5800 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Mon, 30 Dec 2024 13:03:22 -0300 Subject: [PATCH 14/26] feature: add correct types --- apps/web-mobile/src/components/ui/radioBox.tsx | 5 ++++- .../settings/components/profile/profile-form/index.tsx | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/web-mobile/src/components/ui/radioBox.tsx b/apps/web-mobile/src/components/ui/radioBox.tsx index 1f7d14e8..372f26a1 100644 --- a/apps/web-mobile/src/components/ui/radioBox.tsx +++ b/apps/web-mobile/src/components/ui/radioBox.tsx @@ -1,7 +1,10 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { Label } from '@/components/ui/label'; -const cssmap: any = { +type cssmapType = { + [id: string]: string; +}; +const cssmap: cssmapType = { 'option-hodler': 'option-hodler', 'option-recycler': 'option-recycler', 'option-waste': 'option-waste', diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index 8b30a321..7648b7c4 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -38,7 +38,11 @@ const profileFormSchema = z.object({ type ProfileFormValues = z.infer; -const cssmap: any = { +type cssmapType = { + [id: string]: string; +}; + +const cssmap: cssmapType = { 'option-hodler-box': 'option-hodler-box', 'option-recycler-box': 'option-recycler-box', 'option-waste-box': 'option-waste-box', @@ -158,7 +162,7 @@ export default function ProfileForm() {
- {/* */} + From 127301c6b0285b2171e07c83434b47b95f9748ab Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Mon, 30 Dec 2024 15:05:25 -0300 Subject: [PATCH 15/26] Feature: add success, focus and error styles on inputs --- apps/web-mobile/src/components/ui/input.tsx | 28 +++++++++---------- .../components/profile/profile-form/index.tsx | 17 +++++++++-- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/apps/web-mobile/src/components/ui/input.tsx b/apps/web-mobile/src/components/ui/input.tsx index 61f5d546..68dff9f4 100644 --- a/apps/web-mobile/src/components/ui/input.tsx +++ b/apps/web-mobile/src/components/ui/input.tsx @@ -4,21 +4,19 @@ import { cn } from '@/utils/cn'; export interface InputProps extends React.InputHTMLAttributes {} -const Input = React.forwardRef( - ({ className, type, ...props }, ref) => { - return ( - - ); - }, -); +const Input = React.forwardRef(({ className, type, ...props }, ref) => { + return ( + + ); +}); Input.displayName = 'Input'; export { Input }; diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index 7648b7c4..de044d14 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -90,7 +90,10 @@ export default function ProfileForm() { * - + @@ -107,7 +110,11 @@ export default function ProfileForm() { * - + @@ -122,7 +129,11 @@ export default function ProfileForm() { Email - + From 54e9d27712b1d2270d866c5207346d47e6732e56 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Mon, 30 Dec 2024 16:45:05 -0300 Subject: [PATCH 16/26] feature: add styles for inputs --- .../components/profile/profile-form/index.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index de044d14..924b0fdc 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -79,7 +79,7 @@ export default function ProfileForm() {
-
+
@@ -113,7 +116,8 @@ export default function ProfileForm() { @@ -126,13 +130,14 @@ export default function ProfileForm() { control={form.control} name="email" render={({ field }) => ( - + Email @@ -158,7 +163,7 @@ export default function ProfileForm() { #${cssmap[radioActive]}]:border-blue-500`} + className={`grid grid-cols-6 [&[data-active='${cssmap[radioActive]}']>#${cssmap[radioActive]}]:border-blue-500 max-md:grid-cols-2`} data-active={radioActive} > From 85eeba426ab59cf58a36028f4c93240798a1c403 Mon Sep 17 00:00:00 2001 From: Lucas-Bento-D Date: Mon, 30 Dec 2024 17:57:53 -0300 Subject: [PATCH 17/26] feature: styles for radiobox check --- apps/web-mobile/src/components/ui/radioBox.tsx | 5 ++++- .../settings/components/profile/profile-form/index.tsx | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/web-mobile/src/components/ui/radioBox.tsx b/apps/web-mobile/src/components/ui/radioBox.tsx index 372f26a1..cdbc2907 100644 --- a/apps/web-mobile/src/components/ui/radioBox.tsx +++ b/apps/web-mobile/src/components/ui/radioBox.tsx @@ -19,7 +19,7 @@ export const RadioBox = ({ beforeText, id, name, activeState }: Props) => { return (
#${cssmap[id]}]:hidden`} + className={`relative flex items-center space-x-2 rounded-lg border-2 px-4 py-6 [&>#${cssmap[id]}]:hidden`} > activeState(`${id}-box`)} />
@@ -28,6 +28,9 @@ export const RadioBox = ({ beforeText, id, name, activeState }: Props) => { {name}
+ + ✓ +
); }; diff --git a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx index 924b0fdc..122d37fa 100644 --- a/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx +++ b/apps/web-mobile/src/modules/settings/components/profile/profile-form/index.tsx @@ -163,7 +163,7 @@ export default function ProfileForm() { #${cssmap[radioActive]}]:border-blue-500 max-md:grid-cols-2`} + className={`grid grid-cols-6 [&[data-active='${cssmap[radioActive]}']>#${cssmap[radioActive]}]:border-blue-500 max-md:grid-cols-2 [&[data-active='${cssmap[radioActive]}']>#${cssmap[radioActive]}>.checked-box-symbol]:block`} data-active={radioActive} > From 6a151f75cf779b80d1da056aa55c01c3ad55ea9f Mon Sep 17 00:00:00 2001 From: Yuri Mutti Date: Sat, 28 Dec 2024 01:03:48 -0300 Subject: [PATCH 18/26] feat; create audit and report modals --- apps/web-mobile/src/app.tsx | 6 +- .../src/components/ui/alert-dialog.tsx | 106 ++++++ apps/web-mobile/src/components/ui/badge.tsx | 29 ++ apps/web-mobile/src/components/ui/dialog.tsx | 46 +-- .../src/components/ui/scroll-area.tsx | 40 +++ apps/web-mobile/src/components/ui/tabs.tsx | 55 +++ apps/web-mobile/src/entities/audit/index.ts | 9 + apps/web-mobile/src/entities/report/index.ts | 33 +- apps/web-mobile/src/entities/user/index.ts | 10 +- .../src/layouts/header/menu/index.tsx | 22 +- apps/web-mobile/src/libs/axios.ts | 28 -- apps/web-mobile/src/libs/axios/index.ts | 12 + .../web-mobile/src/libs/axios/interceptors.ts | 64 ++++ apps/web-mobile/src/libs/axios/types.ts | 18 + apps/web-mobile/src/main.tsx | 4 +- .../audits/components/audit-modal/index.tsx | 161 +++++++++ .../modules/audits/components/list/index.tsx | 84 +++++ .../components/list/table/columns/index.tsx | 44 +++ .../audits/components/list/table/index.tsx | 59 ++++ .../src/modules/audits/screens/main/index.tsx | 13 +- .../modules/audits/services/audits/index.ts | 86 +++++ .../modules/audits/services/audits/keys.ts | 5 + .../modules/audits/services/audits/types.ts | 13 + .../dashboard/componentes/cards/index.tsx | 4 +- .../dashboard/componentes/chart/constants.ts | 20 +- .../dashboard/componentes/chart/index.tsx | 62 ++-- .../src/modules/error/screens/error/index.tsx | 10 +- .../modules/reports/components/form/index.tsx | 332 ++++++++---------- .../modules/reports/components/list/index.tsx | 15 +- .../components/list/table/columns/index.tsx | 28 +- .../components/reports-modal/constants.ts | 9 + .../components/reports-modal/index.tsx | 63 ++++ .../modules/reports/screens/main/index.tsx | 33 +- .../modules/reports/screens/submit/index.tsx | 9 - apps/web-mobile/src/pages/audits/index.tsx | 4 +- .../src/pages/reports/submit/index.tsx | 7 - .../reports => }/services/reports/index.ts | 28 +- .../reports => }/services/reports/keys.ts | 2 + .../reports => }/services/reports/types.ts | 0 apps/web-mobile/src/services/users/types.ts | 20 +- package.json | 4 +- pnpm-lock.yaml | 311 ++++++++++++++-- 42 files changed, 1481 insertions(+), 427 deletions(-) create mode 100644 apps/web-mobile/src/components/ui/alert-dialog.tsx create mode 100644 apps/web-mobile/src/components/ui/badge.tsx create mode 100644 apps/web-mobile/src/components/ui/scroll-area.tsx create mode 100644 apps/web-mobile/src/components/ui/tabs.tsx create mode 100644 apps/web-mobile/src/entities/audit/index.ts delete mode 100644 apps/web-mobile/src/libs/axios.ts create mode 100644 apps/web-mobile/src/libs/axios/index.ts create mode 100644 apps/web-mobile/src/libs/axios/interceptors.ts create mode 100644 apps/web-mobile/src/libs/axios/types.ts create mode 100644 apps/web-mobile/src/modules/audits/components/audit-modal/index.tsx create mode 100644 apps/web-mobile/src/modules/audits/components/list/index.tsx create mode 100644 apps/web-mobile/src/modules/audits/components/list/table/columns/index.tsx create mode 100644 apps/web-mobile/src/modules/audits/components/list/table/index.tsx create mode 100644 apps/web-mobile/src/modules/audits/services/audits/index.ts create mode 100644 apps/web-mobile/src/modules/audits/services/audits/keys.ts create mode 100644 apps/web-mobile/src/modules/audits/services/audits/types.ts create mode 100644 apps/web-mobile/src/modules/reports/components/reports-modal/constants.ts create mode 100644 apps/web-mobile/src/modules/reports/components/reports-modal/index.tsx delete mode 100644 apps/web-mobile/src/modules/reports/screens/submit/index.tsx delete mode 100644 apps/web-mobile/src/pages/reports/submit/index.tsx rename apps/web-mobile/src/{modules/reports => }/services/reports/index.ts (71%) rename apps/web-mobile/src/{modules/reports => }/services/reports/keys.ts (68%) rename apps/web-mobile/src/{modules/reports => }/services/reports/types.ts (100%) diff --git a/apps/web-mobile/src/app.tsx b/apps/web-mobile/src/app.tsx index 81277f55..09d8e4bf 100644 --- a/apps/web-mobile/src/app.tsx +++ b/apps/web-mobile/src/app.tsx @@ -20,7 +20,7 @@ import Reports from '@/pages/reports'; import Audits from './pages/audits'; import { useAuth0 } from '@auth0/auth0-react'; import { useEffect } from 'react'; -import { addAccessTokenInterceptor } from './libs'; +import { addAccessTokenInterceptor } from './libs/axios/interceptors'; import ProtectedRoutes from './components/protected-router'; const router = createBrowserRouter([ @@ -41,10 +41,6 @@ const router = createBrowserRouter([ element: , path: '/reports', }, - { - element: , - path: '/reports/submit', - }, { element: , path: '/audits', diff --git a/apps/web-mobile/src/components/ui/alert-dialog.tsx b/apps/web-mobile/src/components/ui/alert-dialog.tsx new file mode 100644 index 00000000..669037b6 --- /dev/null +++ b/apps/web-mobile/src/components/ui/alert-dialog.tsx @@ -0,0 +1,106 @@ +'use client'; + +import * as React from 'react'; +import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'; + +import { cn } from '@/utils/cn'; +import { buttonVariants } from '@/components/ui/button'; + +const AlertDialog = AlertDialogPrimitive.Root; + +const AlertDialogTrigger = AlertDialogPrimitive.Trigger; + +const AlertDialogPortal = AlertDialogPrimitive.Portal; + +const AlertDialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName; + +const AlertDialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + +)); +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName; + +const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes) => ( +
+); +AlertDialogHeader.displayName = 'AlertDialogHeader'; + +const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes) => ( +
+); +AlertDialogFooter.displayName = 'AlertDialogFooter'; + +const AlertDialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName; + +const AlertDialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName; + +const AlertDialogAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName; + +const AlertDialogCancel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName; + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +}; diff --git a/apps/web-mobile/src/components/ui/badge.tsx b/apps/web-mobile/src/components/ui/badge.tsx new file mode 100644 index 00000000..ffca01e9 --- /dev/null +++ b/apps/web-mobile/src/components/ui/badge.tsx @@ -0,0 +1,29 @@ +import * as React from 'react'; +import { cva, type VariantProps } from 'class-variance-authority'; + +import { cn } from '@/utils/cn'; + +const badgeVariants = cva( + 'inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', + { + variants: { + variant: { + default: 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80', + secondary: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80', + destructive: 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80', + outline: 'text-foreground', + }, + }, + defaultVariants: { + variant: 'default', + }, + } +); + +export interface BadgeProps extends React.HTMLAttributes, VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return
; +} + +export { Badge, badgeVariants }; diff --git a/apps/web-mobile/src/components/ui/dialog.tsx b/apps/web-mobile/src/components/ui/dialog.tsx index 3d979ce6..d465f042 100644 --- a/apps/web-mobile/src/components/ui/dialog.tsx +++ b/apps/web-mobile/src/components/ui/dialog.tsx @@ -1,7 +1,6 @@ 'use client'; import * as React from 'react'; - import * as DialogPrimitive from '@radix-ui/react-dialog'; import { X } from 'lucide-react'; @@ -22,8 +21,8 @@ const DialogOverlay = React.forwardRef< @@ -39,14 +38,14 @@ const DialogContent = React.forwardRef< {children} - - + + Close @@ -54,19 +53,14 @@ const DialogContent = React.forwardRef< )); DialogContent.displayName = DialogPrimitive.Content.displayName; -function DialogHeader({ className, ...props }: React.HTMLAttributes) { - return
; -} +const DialogHeader = ({ className, ...props }: React.HTMLAttributes) => ( +
+); DialogHeader.displayName = 'DialogHeader'; -function DialogFooter({ className, ...props }: React.HTMLAttributes) { - return ( -
- ); -} +const DialogFooter = ({ className, ...props }: React.HTMLAttributes) => ( +
+); DialogFooter.displayName = 'DialogFooter'; const DialogTitle = React.forwardRef< @@ -85,23 +79,19 @@ const DialogDescription = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( - + )); DialogDescription.displayName = DialogPrimitive.Description.displayName; export { Dialog, + DialogPortal, + DialogOverlay, + DialogTrigger, DialogClose, DialogContent, - DialogDescription, - DialogFooter, DialogHeader, - DialogOverlay, - DialogPortal, + DialogFooter, DialogTitle, - DialogTrigger, + DialogDescription, }; diff --git a/apps/web-mobile/src/components/ui/scroll-area.tsx b/apps/web-mobile/src/components/ui/scroll-area.tsx new file mode 100644 index 00000000..2d09eebc --- /dev/null +++ b/apps/web-mobile/src/components/ui/scroll-area.tsx @@ -0,0 +1,40 @@ +'use client'; + +import * as React from 'react'; +import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'; + +import { cn } from '@/utils/cn'; + +const ScrollArea = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children} + + + +)); +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName; + +const ScrollBar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = 'vertical', ...props }, ref) => ( + + + +)); +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName; + +export { ScrollArea, ScrollBar }; diff --git a/apps/web-mobile/src/components/ui/tabs.tsx b/apps/web-mobile/src/components/ui/tabs.tsx new file mode 100644 index 00000000..8ce5a775 --- /dev/null +++ b/apps/web-mobile/src/components/ui/tabs.tsx @@ -0,0 +1,55 @@ +'use client'; + +import * as React from 'react'; +import * as TabsPrimitive from '@radix-ui/react-tabs'; + +import { cn } from '@/utils/cn'; + +const Tabs = TabsPrimitive.Root; + +const TabsList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsList.displayName = TabsPrimitive.List.displayName; + +const TabsTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; + +const TabsContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsContent.displayName = TabsPrimitive.Content.displayName; + +export { Tabs, TabsList, TabsTrigger, TabsContent }; diff --git a/apps/web-mobile/src/entities/audit/index.ts b/apps/web-mobile/src/entities/audit/index.ts new file mode 100644 index 00000000..7951cb19 --- /dev/null +++ b/apps/web-mobile/src/entities/audit/index.ts @@ -0,0 +1,9 @@ +export interface Audit { + id: string; + reportId: string; + audited?: boolean; + auditorId?: string | null; + comments: string | null; + createdAt: string; + updatedAt: string; +} diff --git a/apps/web-mobile/src/entities/report/index.ts b/apps/web-mobile/src/entities/report/index.ts index 3ccb8ece..76cd26f5 100644 --- a/apps/web-mobile/src/entities/report/index.ts +++ b/apps/web-mobile/src/entities/report/index.ts @@ -1,3 +1,14 @@ +import { Audit } from '../audit'; +import { User } from '../user'; + +export interface Metadata { + attributes?: { trait_type: string; value: string | undefined }[]; + description?: string; + name?: string; + image?: string | Buffer; + [key: string]: unknown; +} + export const MATERIAL_TYPES = { PLASTIC: 'PLASTIC', PAPER: 'PAPER', @@ -11,15 +22,29 @@ export const MATERIAL_TYPES = { export type MaterialType = keyof typeof MATERIAL_TYPES; export interface Material { - weightKg: number; - materialType: MaterialType; + [MATERIAL_TYPES.METAL]?: number; + [MATERIAL_TYPES.PLASTIC]?: number; + [MATERIAL_TYPES.PAPER]?: number; + [MATERIAL_TYPES.GLASS]?: number; + [MATERIAL_TYPES.TEXTILE]?: number; + [MATERIAL_TYPES.LANDFILL_WASTE]?: number; + // Add more residue types as needed } +export type Materials = Material[]; + export interface RecyclingReport { id: string; reportDate: string; - materials: Material[]; + materials: Material; audited: boolean; residueEvidence: string; - metadata: Record; + metadata: Metadata; + submittedBy: string; + phone?: string; + walletAddress?: string; + createdAt: string; + updatedAt: string; + user: User; + audits: Audit[]; } diff --git a/apps/web-mobile/src/entities/user/index.ts b/apps/web-mobile/src/entities/user/index.ts index a02c4c82..24dc90e9 100644 --- a/apps/web-mobile/src/entities/user/index.ts +++ b/apps/web-mobile/src/entities/user/index.ts @@ -1,15 +1,15 @@ import { RecyclingReport } from '@/entities/report'; export type User = { - phone: string | null; - walletAddress: string | null; + phone?: string | null; + walletAddress?: string | null; id: string; name: string; email: string; authProvider: string | null; authId: string | null; picture: string | null; - createdAt: Date; - updatedAt: Date; - recyclingReports: RecyclingReport[]; + createdAt: string; + updatedAt: string; + recyclingReports?: RecyclingReport[]; }; diff --git a/apps/web-mobile/src/layouts/header/menu/index.tsx b/apps/web-mobile/src/layouts/header/menu/index.tsx index fe099b1f..a5124ad6 100644 --- a/apps/web-mobile/src/layouts/header/menu/index.tsx +++ b/apps/web-mobile/src/layouts/header/menu/index.tsx @@ -37,8 +37,8 @@ export function Menu() { const menuItems = [ { label: 'Dashboard', icon: 'material-symbols-light:team-dashboard-outline', route: ROUTES.PRIVATE.DASHBOARD() }, { label: 'Reports', icon: 'ph:recycle', route: ROUTES.PRIVATE.REPORTS() }, + { label: 'Audits', icon: 'ic:check-circle', route: ROUTES.PRIVATE.AUDITS() }, // { label: 'KYC', icon: 'ic:sharp-admin-panel-settings', route: ROUTES.PRIVATE.KYC() }, - // { label: 'Audits', icon: 'ic:check-circle', route: ROUTES.PRIVATE.AUDITS() }, // { label: 'Admin', icon: 'ic:sharp-admin-panel-settings', route: ROUTES.PRIVATE.AUDITS() }, ]; @@ -76,7 +76,7 @@ export function Menu() { -
-
+
+
setIsMobileMenuOpen(false)}> Recy Logo
-