From d4c18fff2c3a5d9980f4f2ba18575e0a5a2d361c Mon Sep 17 00:00:00 2001 From: kirill Date: Mon, 7 Jul 2025 16:11:59 +0300 Subject: [PATCH 1/9] feat: add MoreButton, add modal for reporting abuse, add handler, responsive design, --- packages/apps/human-app/frontend/package.json | 1 + packages/apps/human-app/frontend/src/main.tsx | 3 + .../modules/worker/jobs/components/index.ts | 3 +- .../worker/jobs/components/more-button.tsx | 97 +++++++++++++++++++ .../jobs/components/my-jobs-table-actions.tsx | 30 ++---- .../worker/jobs/components/reject-button.tsx | 27 ------ .../jobs/components/report-abuse-modal.tsx | 72 ++++++++++++++ .../my-jobs/components/desktop/columns.tsx | 9 +- .../components/mobile/my-jobs-list-mobile.tsx | 2 +- .../worker/jobs/services/jobs.service.ts | 24 ++++- .../frontend/src/modules/worker/jobs/types.ts | 6 ++ .../frontend/src/shared/styles/theme.ts | 7 ++ yarn.lock | 8 ++ 13 files changed, 238 insertions(+), 51 deletions(-) create mode 100644 packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx delete mode 100644 packages/apps/human-app/frontend/src/modules/worker/jobs/components/reject-button.tsx create mode 100644 packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx diff --git a/packages/apps/human-app/frontend/package.json b/packages/apps/human-app/frontend/package.json index 8180ab4879..b8912e8602 100644 --- a/packages/apps/human-app/frontend/package.json +++ b/packages/apps/human-app/frontend/package.json @@ -20,6 +20,7 @@ "@emotion/styled": "^11.11.0", "@faker-js/faker": "^9.7.0", "@fontsource/inter": "^5.0.17", + "@fontsource/roboto": "^5.2.6", "@hcaptcha/react-hcaptcha": "^0.3.6", "@hookform/resolvers": "^5.0.1", "@human-protocol/sdk": "workspace:*", diff --git a/packages/apps/human-app/frontend/src/main.tsx b/packages/apps/human-app/frontend/src/main.tsx index a8fa0e6415..ccf792a2b6 100644 --- a/packages/apps/human-app/frontend/src/main.tsx +++ b/packages/apps/human-app/frontend/src/main.tsx @@ -12,6 +12,9 @@ import '@fontsource/inter/400.css'; import '@fontsource/inter/500.css'; import '@fontsource/inter/600.css'; import '@fontsource/inter/800.css'; +import '@fontsource/roboto'; +import '@fontsource/roboto/400.css'; +import '@fontsource/roboto/500.css'; import { WalletConnectProvider } from '@/shared/contexts/wallet-connect'; import { Web3AuthProvider } from '@/modules/auth-web3/context/web3-auth-context'; import { JWTExpirationCheck } from '@/shared/contexts/jwt-expiration-check'; diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/index.ts b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/index.ts index 9dee5f52de..ca383549de 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/index.ts +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/index.ts @@ -2,6 +2,7 @@ export * from './evm-address'; export * from './jobs-tab-panel'; export * from './my-jobs-table-actions'; export * from './escrow-address-search-form'; -export * from './reject-button'; export * from './reward-amount'; export * from './sorting'; +export * from './more-button'; +export * from './report-abuse-modal'; diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx new file mode 100644 index 0000000000..ead9894809 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx @@ -0,0 +1,97 @@ +/* eslint-disable camelcase -- ...*/ +import { useState } from 'react'; +import MoreHorizIcon from '@mui/icons-material/MoreHoriz'; +import { Button, MenuList, ListItemButton, Popover } from '@mui/material'; +import { useParams } from 'react-router-dom'; +import { useModal } from '@/shared/contexts/modal-context'; +import { useIsMobile } from '@/shared/hooks/use-is-mobile'; +import { useResignJobMutation } from '../my-jobs/hooks'; +import { type MyJob } from '../schemas'; +import { ReportAbuseModal } from './report-abuse-modal'; + +interface MoreButtonProps { + job: MyJob; + isDisabled: boolean; +} + +export function MoreButton({ job, isDisabled }: Readonly) { + const [anchorEl, setAnchorEl] = useState(null); + const { address: oracleAddress } = useParams<{ address: string }>(); + const { mutate: rejectTaskMutation } = useResignJobMutation(); + const { openModal, closeModal } = useModal(); + const isMobile = useIsMobile(); + + const isOpen = Boolean(anchorEl); + + const handleCancelTask = () => { + setAnchorEl(null); + rejectTaskMutation({ + oracle_address: oracleAddress ?? '', + assignment_id: job.assignment_id, + }); + }; + + const handleOpenReportAbuseModal = () => { + setAnchorEl(null); + openModal({ + content: ( + + ), + showCloseButton: false, + }); + }; + + return ( + <> + + { + setAnchorEl(null); + }} + anchorOrigin={{ + vertical: isMobile ? 'top' : 'bottom', + horizontal: 'right', + }} + transformOrigin={{ + vertical: isMobile ? 'bottom' : 'top', + horizontal: 'right', + }} + slotProps={{ + paper: { + sx: { + mt: isMobile ? 0 : 1, + }, + }, + }} + > + + Cancel + + Report Abuse + + + + + ); +} diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/my-jobs-table-actions.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/my-jobs-table-actions.tsx index 5ad4849298..886dc72875 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/my-jobs-table-actions.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/my-jobs-table-actions.tsx @@ -1,11 +1,9 @@ -/* eslint-disable camelcase -- ...*/ -import { Link, useParams } from 'react-router-dom'; +import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { TableButton } from '@/shared/components/ui/table-button'; -import { useResignJobMutation } from '../my-jobs/hooks'; import { MyJobStatus } from '../types'; import { type MyJob } from '../schemas'; -import { RejectButton } from './reject-button'; +import { MoreButton } from './more-button'; interface MyJobsTableRejectActionProps { job: MyJob; @@ -15,10 +13,7 @@ export function MyJobsTableActions({ job, }: Readonly) { const { t } = useTranslation(); - const { mutate: rejectTaskMutation, isPending: isRejectPending } = - useResignJobMutation(); - const { address: oracleAddress } = useParams<{ address: string }>(); - const buttonDisabled = job.status !== MyJobStatus.ACTIVE || isRejectPending; + const isDisabled = job.status !== MyJobStatus.ACTIVE; if (!job.url) { return null; @@ -28,24 +23,19 @@ export function MyJobsTableActions({ <> {t('worker.jobs.solve')} - { - rejectTaskMutation({ - oracle_address: oracleAddress ?? '', - assignment_id: job.assignment_id, - }); - }} - /> + ); } diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/reject-button.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/reject-button.tsx deleted file mode 100644 index d3f78d05ea..0000000000 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/reject-button.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import CloseIcon from '@mui/icons-material/Close'; -import type { CustomButtonProps } from '@/shared/components/ui/button'; -import { TableButton } from '@/shared/components/ui/table-button'; - -export function RejectButton(props: CustomButtonProps) { - return ( - - - - ); -} diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx new file mode 100644 index 0000000000..b811ba8db0 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx @@ -0,0 +1,72 @@ +/* eslint-disable camelcase */ +import { useState } from 'react'; +import { Box, Button, Stack, Typography, TextField } from '@mui/material'; +import { useIsMobile } from '@/shared/hooks/use-is-mobile'; +import { reportAbuse } from '../services/jobs.service'; + +interface ReportAbuseModalProps { + escrowAddress: string; + chainId: number; + close: () => void; +} + +export function ReportAbuseModal({ + escrowAddress, + chainId, + close, +}: Readonly) { + const [reason, setReason] = useState(''); + const isMobile = useIsMobile(); + + const handleReportAbuse = () => { + close(); + void reportAbuse({ + escrow_address: escrowAddress, + chain_id: chainId, + reason: reason.trim(), + }); + }; + + return ( + + + Report Abuse + + + Notice something inappropriate or incorrect? Let us know if this task + contains harmful, offensive, or misleading content. Your report will be + reviewed confidentially. + + { + setReason(e.target.value); + }} + /> + + + + + + ); +} diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/components/desktop/columns.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/components/desktop/columns.tsx index 4d7aa02284..2f6767d2f6 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/components/desktop/columns.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/components/desktop/columns.tsx @@ -135,7 +135,14 @@ export const getColumnsDefinition = ({ size: 100, enableSorting: true, Cell: (props) => ( - + ), diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/components/mobile/my-jobs-list-mobile.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/components/mobile/my-jobs-list-mobile.tsx index ea51b3ce32..02df479459 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/components/mobile/my-jobs-list-mobile.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/components/mobile/my-jobs-list-mobile.tsx @@ -181,7 +181,7 @@ export function MyJobsListMobile() { sx={{ display: 'flex', justifyContent: 'flex-end', - gap: '1rem', + gap: 1, width: '100%', }} > diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/services/jobs.service.ts b/packages/apps/human-app/frontend/src/modules/worker/jobs/services/jobs.service.ts index 8abcbb9c0c..c74181986e 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/services/jobs.service.ts +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/services/jobs.service.ts @@ -10,6 +10,7 @@ import { type RefreshJobsBody, type RejectTaskBody, type AvailableJobsSuccessResponse, + type ReportAbuseBody, } from '../types'; const apiPaths = { @@ -19,6 +20,7 @@ const apiPaths = { resignJob: '/assignment/resign-job', refreshJobs: '/assignment/refresh', uiConfig: '/ui-config', + reportAbuse: '/abuse/report', }; async function fetchAvailableJobs(args: JobsBody) { @@ -102,4 +104,24 @@ async function refreshJobs(data: RefreshJobsBody) { } } -export { fetchAvailableJobs, fetchMyJobs, assignJob, resignJob, refreshJobs }; +async function reportAbuse(data: ReportAbuseBody) { + try { + await authorizedHumanAppApiClient.post(apiPaths.reportAbuse, { + body: { ...data }, + }); + } catch (error: unknown) { + if (error instanceof ApiClientError) { + throw error; + } + throw new Error('Failed to report abuse'); + } +} + +export { + fetchAvailableJobs, + fetchMyJobs, + assignJob, + resignJob, + refreshJobs, + reportAbuse, +}; diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/types.ts b/packages/apps/human-app/frontend/src/modules/worker/jobs/types.ts index cb6f85f3c4..d2317b7cf0 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/types.ts +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/types.ts @@ -52,3 +52,9 @@ export interface AssignJobBody { export interface RefreshJobsBody { oracle_address: string; } + +export interface ReportAbuseBody { + escrow_address: string; + chain_id: number; + reason: string; +} diff --git a/packages/apps/human-app/frontend/src/shared/styles/theme.ts b/packages/apps/human-app/frontend/src/shared/styles/theme.ts index 4fce1894b0..871d14719e 100644 --- a/packages/apps/human-app/frontend/src/shared/styles/theme.ts +++ b/packages/apps/human-app/frontend/src/shared/styles/theme.ts @@ -32,6 +32,13 @@ export const theme: ThemeOptions = { }, }, }, + MuiListItemButton: { + styleOverrides: { + root: { + fontFamily: 'Roboto', + }, + }, + }, MuiCheckbox: { styleOverrides: { root: { diff --git a/yarn.lock b/yarn.lock index df8db15002..299c0d183d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3372,6 +3372,13 @@ __metadata: languageName: node linkType: hard +"@fontsource/roboto@npm:^5.2.6": + version: 5.2.6 + resolution: "@fontsource/roboto@npm:5.2.6" + checksum: 10c0/a2fbadf2f3b8ebb859e7b13ad82d25e8b43901c30ad93b08095c201617fcfded279d99e64a7b110614d2a1b5bca77631df7d009abf1ad6c6a4df301ceb330a51 + languageName: node + linkType: hard + "@gerrit0/mini-shiki@npm:^3.7.0": version: 3.7.0 resolution: "@gerrit0/mini-shiki@npm:3.7.0" @@ -4199,6 +4206,7 @@ __metadata: "@emotion/styled": "npm:^11.11.0" "@faker-js/faker": "npm:^9.7.0" "@fontsource/inter": "npm:^5.0.17" + "@fontsource/roboto": "npm:^5.2.6" "@hcaptcha/react-hcaptcha": "npm:^0.3.6" "@hookform/resolvers": "npm:^5.0.1" "@human-protocol/sdk": "workspace:*" From 28db4b1557971ba6b53d2063ec0212ce8eaa75ae Mon Sep 17 00:00:00 2001 From: kirill Date: Mon, 7 Jul 2025 23:06:26 +0300 Subject: [PATCH 2/9] fix: correct mapping of abuse report dto; add success and error states --- .../available-jobs/hooks/use-report-abuse.ts | 21 +++ .../jobs/components/report-abuse-modal.tsx | 128 +++++++++++++----- .../worker/jobs/services/jobs.service.ts | 15 +- .../components/ui/modal/global-modal.tsx | 5 + .../reputation-oracle.gateway.ts | 7 +- .../reputation-oracle.mapper.profile.ts | 4 +- 6 files changed, 132 insertions(+), 48 deletions(-) create mode 100644 packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-report-abuse.ts diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-report-abuse.ts b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-report-abuse.ts new file mode 100644 index 0000000000..f92e337bac --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-report-abuse.ts @@ -0,0 +1,21 @@ +import { useMutation } from '@tanstack/react-query'; +import { ApiClientError } from '@/api/http-api-client'; +import * as jobsService from '../../services/jobs.service'; +import type { ReportAbuseBody } from '../../types'; + +interface ReportAbuseMutationOptions { + onSuccess?: (status: number) => void; + onError?: (status: number, message: string) => void; +} + +export function useReportAbuseMutation(options?: ReportAbuseMutationOptions) { + return useMutation({ + mutationFn: (data: ReportAbuseBody) => jobsService.reportAbuse(data), + mutationKey: ['reportAbuse'], + onError: (error) => { + if (error instanceof ApiClientError) { + options?.onError?.(error.status, error.message); + } + }, + }); +} diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx index b811ba8db0..6289d7304f 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx @@ -1,8 +1,11 @@ /* eslint-disable camelcase */ import { useState } from 'react'; import { Box, Button, Stack, Typography, TextField } from '@mui/material'; +import ErrorIcon from '@mui/icons-material/Error'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import { useIsMobile } from '@/shared/hooks/use-is-mobile'; -import { reportAbuse } from '../services/jobs.service'; +import { colorPalette } from '@/shared/styles/color-palette'; +import { useReportAbuseMutation } from '../available-jobs/hooks/use-report-abuse'; interface ReportAbuseModalProps { escrowAddress: string; @@ -10,17 +13,66 @@ interface ReportAbuseModalProps { close: () => void; } +function ErrorState({ + error, + onClose, +}: { + error: string; + onClose: () => void; +}) { + const errorColor = colorPalette.error.main; + return ( + + + + {error} + + + + ); +} + +function SuccessState({ onClose }: { onClose: () => void }) { + return ( + + + + + ); +} + export function ReportAbuseModal({ escrowAddress, chainId, close, }: Readonly) { const [reason, setReason] = useState(''); + const [error, setError] = useState(''); const isMobile = useIsMobile(); + const { + mutate: reportAbuseMutation, + isSuccess, + isError, + isIdle, + } = useReportAbuseMutation({ + onError: (status) => { + if (status === 422) { + setError('Abuse has already been reported'); + } else { + setError('Something went wrong'); + } + }, + }); + const handleReportAbuse = () => { - close(); - void reportAbuse({ + reportAbuseMutation({ escrow_address: escrowAddress, chain_id: chainId, reason: reason.trim(), @@ -36,37 +88,45 @@ export function ReportAbuseModal({ Report Abuse - - Notice something inappropriate or incorrect? Let us know if this task - contains harmful, offensive, or misleading content. Your report will be - reviewed confidentially. - - { - setReason(e.target.value); - }} - /> - - - - + {isError && } + {isSuccess && } + {isIdle && ( + <> + + Notice something inappropriate or incorrect? Let us know if this + task contains harmful, offensive, or misleading content. Your report + reviewed confidentially. + + { + setReason(e.target.value); + }} + /> + + + + + + )} ); } diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/services/jobs.service.ts b/packages/apps/human-app/frontend/src/modules/worker/jobs/services/jobs.service.ts index c74181986e..166dea37f9 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/services/jobs.service.ts +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/services/jobs.service.ts @@ -104,17 +104,10 @@ async function refreshJobs(data: RefreshJobsBody) { } } -async function reportAbuse(data: ReportAbuseBody) { - try { - await authorizedHumanAppApiClient.post(apiPaths.reportAbuse, { - body: { ...data }, - }); - } catch (error: unknown) { - if (error instanceof ApiClientError) { - throw error; - } - throw new Error('Failed to report abuse'); - } +function reportAbuse(data: ReportAbuseBody) { + return authorizedHumanAppApiClient.post(apiPaths.reportAbuse, { + body: { ...data }, + }); } export { diff --git a/packages/apps/human-app/frontend/src/shared/components/ui/modal/global-modal.tsx b/packages/apps/human-app/frontend/src/shared/components/ui/modal/global-modal.tsx index 8061f5a401..16958d5dc7 100644 --- a/packages/apps/human-app/frontend/src/shared/components/ui/modal/global-modal.tsx +++ b/packages/apps/human-app/frontend/src/shared/components/ui/modal/global-modal.tsx @@ -12,6 +12,11 @@ export function GlobalModal() { open={open} onClose={closeModal} onTransitionExited={onTransitionExited} + PaperProps={{ + sx: { + flex: 1, + }, + }} > Date: Tue, 8 Jul 2025 10:49:02 +0300 Subject: [PATCH 3/9] minor refactoring --- .../jobs/available-jobs/hooks/use-report-abuse.ts | 9 +++++---- .../modules/worker/jobs/components/more-button.tsx | 10 ++++++---- .../worker/jobs/components/report-abuse-modal.tsx | 13 +++++++------ 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-report-abuse.ts b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-report-abuse.ts index f92e337bac..5bb6d38a91 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-report-abuse.ts +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-report-abuse.ts @@ -4,17 +4,18 @@ import * as jobsService from '../../services/jobs.service'; import type { ReportAbuseBody } from '../../types'; interface ReportAbuseMutationOptions { - onSuccess?: (status: number) => void; - onError?: (status: number, message: string) => void; + onError?: (status: number) => void; } -export function useReportAbuseMutation(options?: ReportAbuseMutationOptions) { +export function useReportAbuseMutation({ + onError, +}: ReportAbuseMutationOptions) { return useMutation({ mutationFn: (data: ReportAbuseBody) => jobsService.reportAbuse(data), mutationKey: ['reportAbuse'], onError: (error) => { if (error instanceof ApiClientError) { - options?.onError?.(error.status, error.message); + onError?.(error.status); } }, }); diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx index ead9894809..77702d2772 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx @@ -14,7 +14,7 @@ interface MoreButtonProps { isDisabled: boolean; } -export function MoreButton({ job, isDisabled }: Readonly) { +export function MoreButton({ job, isDisabled }: MoreButtonProps) { const [anchorEl, setAnchorEl] = useState(null); const { address: oracleAddress } = useParams<{ address: string }>(); const { mutate: rejectTaskMutation } = useResignJobMutation(); @@ -54,14 +54,15 @@ export function MoreButton({ job, isDisabled }: Readonly) { width: { xs: '48px', md: '30px' }, height: { xs: '48px', md: '30px' }, p: 1, - border: isMobile ? '1px solid #858EC6' : 'none', + border: isMobile ? '1px solid #858ec6' : 'none', borderRadius: '4px', + color: '#858ec6', }} onClick={(e) => { !isDisabled && setAnchorEl(e.currentTarget); }} > - + ) { }} slotProps={{ paper: { + elevation: 8, sx: { - mt: isMobile ? 0 : 1, + mt: isMobile ? -1 : 1, }, }, }} diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx index 6289d7304f..82a451d283 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx @@ -51,7 +51,7 @@ export function ReportAbuseModal({ escrowAddress, chainId, close, -}: Readonly) { +}: ReportAbuseModalProps) { const [reason, setReason] = useState(''); const [error, setError] = useState(''); const isMobile = useIsMobile(); @@ -72,11 +72,12 @@ export function ReportAbuseModal({ }); const handleReportAbuse = () => { - reportAbuseMutation({ - escrow_address: escrowAddress, - chain_id: chainId, - reason: reason.trim(), - }); + reason.trim().length > 0 && + reportAbuseMutation({ + escrow_address: escrowAddress, + chain_id: chainId, + reason: reason.trim(), + }); }; return ( From ecc0d752d7f3fea28541c920d9b1f1cc51d05567 Mon Sep 17 00:00:00 2001 From: kirill Date: Tue, 8 Jul 2025 19:17:13 +0300 Subject: [PATCH 4/9] fix gov banner on mobile, fix header's paddings on mobile --- .../components/governance-banner.tsx | 82 ++++++++----------- .../protected/bottom-menu-items-list.tsx | 3 +- .../components/layout/protected/navbar.tsx | 6 +- .../layout/protected/top-menu-items-list.tsx | 8 +- 4 files changed, 36 insertions(+), 63 deletions(-) diff --git a/packages/apps/human-app/frontend/src/modules/governance-banner/components/governance-banner.tsx b/packages/apps/human-app/frontend/src/modules/governance-banner/components/governance-banner.tsx index 19373ee981..02617421d2 100644 --- a/packages/apps/human-app/frontend/src/modules/governance-banner/components/governance-banner.tsx +++ b/packages/apps/human-app/frontend/src/modules/governance-banner/components/governance-banner.tsx @@ -1,10 +1,9 @@ import AccessTimeIcon from '@mui/icons-material/AccessTime'; -import { Grid, Link as MuiLink, Typography } from '@mui/material'; +import { Box, Grid, Link as MuiLink, Typography } from '@mui/material'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { env } from '@/shared/env'; import { useColorMode } from '@/shared/contexts/color-mode'; -import { useIsMobile } from '@/shared/hooks/use-is-mobile'; import { useWorkerIdentityVerificationStatus } from '@/modules/worker/profile/hooks'; import { useActiveProposalQuery } from '../hooks/use-active-proposal-query'; @@ -13,8 +12,8 @@ export function GovernanceBanner() { const { data, isLoading, isError } = useActiveProposalQuery(); const { isVerificationCompleted } = useWorkerIdentityVerificationStatus(); const { colorPalette } = useColorMode(); + const { text, background } = colorPalette.banner; const [timeRemaining, setTimeRemaining] = useState('00:00:00'); - const isMobile = useIsMobile('lg'); useEffect(() => { if (!data?.deadline) return; @@ -55,52 +54,41 @@ export function GovernanceBanner() { return ( {/* Left side: Countdown & "X votes" */} - - - {t('governance.timeToReveal', 'Time to reveal vote')}: - - - - {timeRemaining} - + + + + {t('governance.timeToReveal', 'Time to reveal vote')}: + + + {timeRemaining} + + {totalVotes} {t('governance.votes', 'votes')} @@ -111,22 +99,16 @@ export function GovernanceBanner() { item xs={12} sm - sx={{ - display: 'flex', - justifyContent: isMobile ? 'flex-start' : 'flex-end', - mt: isMobile ? 2 : 0, - mr: isMobile ? 0 : 2, - }} + display="flex" + justifyContent={{ xs: 'flex-start', sm: 'flex-end' }} > {t('governance.moreDetails', 'More details')} → diff --git a/packages/apps/human-app/frontend/src/router/components/layout/protected/bottom-menu-items-list.tsx b/packages/apps/human-app/frontend/src/router/components/layout/protected/bottom-menu-items-list.tsx index 347a53071e..8bf0bafb4d 100644 --- a/packages/apps/human-app/frontend/src/router/components/layout/protected/bottom-menu-items-list.tsx +++ b/packages/apps/human-app/frontend/src/router/components/layout/protected/bottom-menu-items-list.tsx @@ -13,7 +13,6 @@ import { colorPalette } from '@/shared/styles/color-palette'; import { onlyDarkModeColor } from '@/shared/styles/dark-color-palette'; import { isDrawerItem } from '../helpers'; import { type MenuItem, type DrawerItem } from './drawer-navigation'; -import { NAVBAR_PADDING } from './navbar'; interface MenuItemListProps { handleItemClick: (item: DrawerItem) => void; @@ -37,7 +36,7 @@ export function BottomMenuItemsList({ direction="row" sx={{ width: '100%', - mx: isMobile ? '28px' : NAVBAR_PADDING, + mx: isMobile ? 7 : 2, }} > {item} diff --git a/packages/apps/human-app/frontend/src/router/components/layout/protected/navbar.tsx b/packages/apps/human-app/frontend/src/router/components/layout/protected/navbar.tsx index e8172f18e1..685c95bc61 100644 --- a/packages/apps/human-app/frontend/src/router/components/layout/protected/navbar.tsx +++ b/packages/apps/human-app/frontend/src/router/components/layout/protected/navbar.tsx @@ -9,8 +9,6 @@ import { useIsHCaptchaLabelingPage } from '@/shared/hooks/use-is-hcaptcha-labeli import { useColorMode } from '@/shared/contexts/color-mode'; import { useHandleMainNavIconClick } from '@/shared/hooks/use-handle-main-nav-icon-click'; -export const NAVBAR_PADDING = '16px'; - interface NavbarProps { open: boolean; setOpen: (open: boolean) => void; @@ -74,8 +72,8 @@ export function Navbar({ backgroundColor: colorPalette.backgroundColor, display: { xs: 'flex', md: 'none' }, width: '100%', - px: isMobile ? NAVBAR_PADDING : 0, - py: isMobile ? '32px' : 0, + px: isMobile ? 4 : 0, + py: isMobile ? 3 : 0, zIndex: '130', position: open ? 'sticky' : 'relative', top: open ? '0' : 'unset', diff --git a/packages/apps/human-app/frontend/src/router/components/layout/protected/top-menu-items-list.tsx b/packages/apps/human-app/frontend/src/router/components/layout/protected/top-menu-items-list.tsx index 529a3222f0..972ea1ee56 100644 --- a/packages/apps/human-app/frontend/src/router/components/layout/protected/top-menu-items-list.tsx +++ b/packages/apps/human-app/frontend/src/router/components/layout/protected/top-menu-items-list.tsx @@ -13,7 +13,6 @@ import { colorPalette } from '@/shared/styles/color-palette'; import { onlyDarkModeColor } from '@/shared/styles/dark-color-palette'; import { isDrawerItem } from '../helpers'; import { type DrawerItem, type MenuItem } from './drawer-navigation'; -import { NAVBAR_PADDING } from './navbar'; interface MenuItemListProps { handleItemClick: (item: DrawerItem) => void; @@ -38,12 +37,7 @@ export function TopMenuItemsList({ if (!isDrawerItem(item)) { return ( - + {item} From 238b4e35923d839ac4881f14bbaa6107dd85fff8 Mon Sep 17 00:00:00 2001 From: kirill Date: Wed, 9 Jul 2025 11:30:26 +0300 Subject: [PATCH 5/9] add loading state --- .../worker/jobs/components/report-abuse-modal.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx index 82a451d283..c3310c234d 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx @@ -1,6 +1,13 @@ /* eslint-disable camelcase */ import { useState } from 'react'; -import { Box, Button, Stack, Typography, TextField } from '@mui/material'; +import { + Box, + Button, + CircularProgress, + Stack, + Typography, + TextField, +} from '@mui/material'; import ErrorIcon from '@mui/icons-material/Error'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import { useIsMobile } from '@/shared/hooks/use-is-mobile'; @@ -61,6 +68,7 @@ export function ReportAbuseModal({ isSuccess, isError, isIdle, + isPending, } = useReportAbuseMutation({ onError: (status) => { if (status === 422) { @@ -89,6 +97,7 @@ export function ReportAbuseModal({ Report Abuse + {isPending && } {isError && } {isSuccess && } {isIdle && ( From 3b3988c2aab45ab6d36438c4e75a309066bcd67b Mon Sep 17 00:00:00 2001 From: kirill Date: Fri, 11 Jul 2025 16:12:04 +0300 Subject: [PATCH 6/9] refactor: modal's states --- .../jobs/components/report-abuse-modal.tsx | 143 ++++++++++-------- 1 file changed, 82 insertions(+), 61 deletions(-) diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx index c3310c234d..e6f5d32c35 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx @@ -9,7 +9,7 @@ import { TextField, } from '@mui/material'; import ErrorIcon from '@mui/icons-material/Error'; -import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import SuccessIcon from '@mui/icons-material/CheckCircle'; import { useIsMobile } from '@/shared/hooks/use-is-mobile'; import { colorPalette } from '@/shared/styles/color-palette'; import { useReportAbuseMutation } from '../available-jobs/hooks/use-report-abuse'; @@ -20,36 +20,51 @@ interface ReportAbuseModalProps { close: () => void; } -function ErrorState({ - error, - onClose, -}: { - error: string; - onClose: () => void; -}) { +const ABUSE_ERROR = 'Abuse has already been reported'; + +function ErrorState({ error }: { error: string }) { + const isAbuseError = error === ABUSE_ERROR; const errorColor = colorPalette.error.main; return ( - + - - {error} - - + {isAbuseError ? ( + <> + + Report Already Submitted + + + This case of abuse has already been reported. Our team is currently + reviewing it. + + + ) : ( + + Something went wrong. + + )} ); } -function SuccessState({ onClose }: { onClose: () => void }) { +function SuccessState() { return ( - - + - + + Thank you! + + + Your issue has been successfully reported. Our team has received the + details and will review them shortly. + ); } @@ -72,13 +87,15 @@ export function ReportAbuseModal({ } = useReportAbuseMutation({ onError: (status) => { if (status === 422) { - setError('Abuse has already been reported'); + setError(ABUSE_ERROR); } else { setError('Something went wrong'); } }, }); + const isIdleOrLoading = isIdle || isPending; + const handleReportAbuse = () => { reason.trim().length > 0 && reportAbuseMutation({ @@ -93,50 +110,54 @@ export function ReportAbuseModal({ px={{ xs: 1, md: 5 }} pt={{ xs: 0, md: 3.5 }} pb={{ xs: 1.5, md: 5.5 }} + alignItems="center" > Report Abuse - {isPending && } - {isError && } - {isSuccess && } - {isIdle && ( - <> - - Notice something inappropriate or incorrect? Let us know if this - task contains harmful, offensive, or misleading content. Your report - reviewed confidentially. - - { - setReason(e.target.value); - }} - /> - - - - - + {isIdleOrLoading && ( + + Notice something inappropriate or incorrect? Let us know if this task + contains harmful, offensive, or misleading content. Your report will + be reviewed confidentially. + )} + {isPending && } + {isError && } + {isSuccess && } + { + setReason(e.target.value); + }} + /> + + + + ); } From fb02a4a13be4710126932787db3cb73598d43075 Mon Sep 17 00:00:00 2001 From: kirill Date: Fri, 11 Jul 2025 16:38:16 +0300 Subject: [PATCH 7/9] chore: add translation --- .../worker/jobs/components/more-button.tsx | 8 +++-- .../jobs/components/report-abuse-modal.tsx | 34 +++++++++++-------- .../frontend/src/shared/i18n/en.json | 14 ++++++++ 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx index 77702d2772..4b54f10816 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx @@ -3,6 +3,7 @@ import { useState } from 'react'; import MoreHorizIcon from '@mui/icons-material/MoreHoriz'; import { Button, MenuList, ListItemButton, Popover } from '@mui/material'; import { useParams } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; import { useModal } from '@/shared/contexts/modal-context'; import { useIsMobile } from '@/shared/hooks/use-is-mobile'; import { useResignJobMutation } from '../my-jobs/hooks'; @@ -20,6 +21,7 @@ export function MoreButton({ job, isDisabled }: MoreButtonProps) { const { mutate: rejectTaskMutation } = useResignJobMutation(); const { openModal, closeModal } = useModal(); const isMobile = useIsMobile(); + const { t } = useTranslation(); const isOpen = Boolean(anchorEl); @@ -88,9 +90,11 @@ export function MoreButton({ job, isDisabled }: MoreButtonProps) { }} > - Cancel + + {t('worker.reportAbuse.cancel')} + - Report Abuse + {t('worker.reportAbuse.report')} diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx index e6f5d32c35..3e61f7ea2b 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx @@ -10,6 +10,7 @@ import { } from '@mui/material'; import ErrorIcon from '@mui/icons-material/Error'; import SuccessIcon from '@mui/icons-material/CheckCircle'; +import { useTranslation } from 'react-i18next'; import { useIsMobile } from '@/shared/hooks/use-is-mobile'; import { colorPalette } from '@/shared/styles/color-palette'; import { useReportAbuseMutation } from '../available-jobs/hooks/use-report-abuse'; @@ -23,8 +24,11 @@ interface ReportAbuseModalProps { const ABUSE_ERROR = 'Abuse has already been reported'; function ErrorState({ error }: { error: string }) { + const { t } = useTranslation(); + const isAbuseError = error === ABUSE_ERROR; const errorColor = colorPalette.error.main; + return ( @@ -36,16 +40,15 @@ function ErrorState({ error }: { error: string }) { fontWeight={700} color={errorColor} > - Report Already Submitted + {t('worker.reportAbuse.modalErrorHeader')} - This case of abuse has already been reported. Our team is currently - reviewing it. + {t('worker.reportAbuse.modalErrorParagraph')} ) : ( - Something went wrong. + {t('worker.reportAbuse.modalUnknownError')} )} @@ -53,17 +56,17 @@ function ErrorState({ error }: { error: string }) { } function SuccessState() { + const { t } = useTranslation(); return ( - Thank you! + {t('worker.reportAbuse.modalSuccessHeader')} - Your issue has been successfully reported. Our team has received the - details and will review them shortly. + {t('worker.reportAbuse.modalSuccessParagraph')} ); @@ -77,6 +80,7 @@ export function ReportAbuseModal({ const [reason, setReason] = useState(''); const [error, setError] = useState(''); const isMobile = useIsMobile(); + const { t } = useTranslation(); const { mutate: reportAbuseMutation, @@ -113,13 +117,11 @@ export function ReportAbuseModal({ alignItems="center" > - Report Abuse + {t('worker.reportAbuse.modalHeader')} {isIdleOrLoading && ( - Notice something inappropriate or incorrect? Let us know if this task - contains harmful, offensive, or misleading content. Your report will - be reviewed confidentially. + {t('worker.reportAbuse.modalParagraph')} )} {isPending && } @@ -129,7 +131,7 @@ export function ReportAbuseModal({ fullWidth multiline rows={3} - label="Reason" + label={t('worker.reportAbuse.modalReason')} value={reason} sx={{ display: isIdle ? 'flex' : 'none', @@ -146,7 +148,9 @@ export function ReportAbuseModal({ variant="outlined" disabled={isPending} > - {isIdleOrLoading ? 'Cancel' : 'Close'} + {isIdleOrLoading + ? t('worker.reportAbuse.cancel') + : t('worker.reportAbuse.close')} diff --git a/packages/apps/human-app/frontend/src/shared/i18n/en.json b/packages/apps/human-app/frontend/src/shared/i18n/en.json index 1296e089fc..94c9b5b406 100644 --- a/packages/apps/human-app/frontend/src/shared/i18n/en.json +++ b/packages/apps/human-app/frontend/src/shared/i18n/en.json @@ -303,6 +303,20 @@ }, "registerAddress": { "success": "The address has been successfully registered." + }, + "reportAbuse": { + "modalHeader": "Report Abuse", + "modalParagraph": "Notice something inappropriate or incorrect? Let us know if this task contains harmful, offensive, or misleading content. Your report will be reviewed confidentially.", + "modalReason": "Reason", + "cancel": "Cancel", + "close": "Close", + "report": "Report", + "reportAbuse": "Report Abuse", + "modalSuccessHeader": "Thank you!", + "modalSuccessParagraph": "Your issue has been successfully reported. Our team has received the details and will review them shortly.", + "modalErrorHeader": "Report Already Submitted", + "modalErrorParagraph": "This case of abuse has already been reported. Our team is currently reviewing it.", + "modalUnknownError": "Something went wrong." } }, "operator": { From 9eb6c268967d16c4fb21fe4830e8dbb324b9f5aa Mon Sep 17 00:00:00 2001 From: kirill Date: Fri, 11 Jul 2025 16:44:28 +0300 Subject: [PATCH 8/9] fix: text in more button popover --- .../frontend/src/modules/worker/jobs/components/more-button.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx index 4b54f10816..492459017f 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/more-button.tsx @@ -94,7 +94,7 @@ export function MoreButton({ job, isDisabled }: MoreButtonProps) { {t('worker.reportAbuse.cancel')} - {t('worker.reportAbuse.report')} + {t('worker.reportAbuse.reportAbuse')} From 2bf93fe1a463c7fc064b7fa8cb06759dcdbba26a Mon Sep 17 00:00:00 2001 From: kirill Date: Fri, 11 Jul 2025 16:47:53 +0300 Subject: [PATCH 9/9] fix: rename translation field --- .../src/modules/worker/jobs/components/report-abuse-modal.tsx | 4 ++-- packages/apps/human-app/frontend/src/shared/i18n/en.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx index 3e61f7ea2b..879ebd2c65 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/components/report-abuse-modal.tsx @@ -40,10 +40,10 @@ function ErrorState({ error }: { error: string }) { fontWeight={700} color={errorColor} > - {t('worker.reportAbuse.modalErrorHeader')} + {t('worker.reportAbuse.modalHeaderAlreadyReportedError')} - {t('worker.reportAbuse.modalErrorParagraph')} + {t('worker.reportAbuse.modalParagraphAlreadyReportedError')} ) : ( diff --git a/packages/apps/human-app/frontend/src/shared/i18n/en.json b/packages/apps/human-app/frontend/src/shared/i18n/en.json index 94c9b5b406..5363f1a7b9 100644 --- a/packages/apps/human-app/frontend/src/shared/i18n/en.json +++ b/packages/apps/human-app/frontend/src/shared/i18n/en.json @@ -314,8 +314,8 @@ "reportAbuse": "Report Abuse", "modalSuccessHeader": "Thank you!", "modalSuccessParagraph": "Your issue has been successfully reported. Our team has received the details and will review them shortly.", - "modalErrorHeader": "Report Already Submitted", - "modalErrorParagraph": "This case of abuse has already been reported. Our team is currently reviewing it.", + "modalHeaderAlreadyReportedError": "Report Already Submitted", + "modalParagraphAlreadyReportedError": "This case of abuse has already been reported. Our team is currently reviewing it.", "modalUnknownError": "Something went wrong." } },