Skip to content

Commit 7c1b969

Browse files
authored
[HUMAN App] refactor: my jobs table components (#3186)
1 parent 173f8f0 commit 7c1b969

10 files changed

Lines changed: 264 additions & 262 deletions

File tree

packages/apps/human-app/frontend/src/modules/worker/jobs/components/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
export * from './evm-address';
22
export * from './jobs-tab-panel';
3-
export * from './my-jobs-data';
43
export * from './my-jobs-table-actions';
54
export * from './escrow-address-search-form';
65
export * from './reject-button';

packages/apps/human-app/frontend/src/modules/worker/jobs/components/my-jobs-table-actions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
44
import { TableButton } from '@/shared/components/ui/table-button';
55
import { useRejectTaskMutation } from '../my-jobs/hooks';
66
import { MyJobStatus } from '../types';
7-
import { type MyJob } from './my-jobs-data';
7+
import { type MyJob } from '../my-jobs/schemas';
88
import { RejectButton } from './reject-button';
99

1010
interface MyJobsTableRejectActionProps {

packages/apps/human-app/frontend/src/modules/worker/jobs/hooks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export * from './use-job-types-oracles-table';
44
export * from './use-jobs-filter-store';
55
export * from './use-my-jobs-filter-store';
66
export * from './use-get-ui-config';
7+
export * from './use-get-my-jobs-data';

packages/apps/human-app/frontend/src/modules/worker/jobs/components/my-jobs-data.ts renamed to packages/apps/human-app/frontend/src/modules/worker/jobs/hooks/use-get-my-jobs-data.ts

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,14 @@
1-
/* eslint-disable camelcase -- api response*/
1+
/* eslint-disable camelcase */
22
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
3-
import { z } from 'zod';
43
import { useParams } from 'react-router-dom';
54
import { apiClient } from '@/api/api-client';
65
import { apiPaths } from '@/api/api-paths';
76
import { stringifyUrlQueryObject } from '@/shared/helpers/transfomers';
8-
import { createPaginationSchema } from '@/shared/helpers/pagination';
9-
import { MyJobStatus, UNKNOWN_JOB_STATUS } from '../types';
10-
import { type MyJobsFilterStoreProps, useMyJobsFilterStore } from '../hooks';
11-
12-
const myJobSchema = z.object({
13-
assignment_id: z.string(),
14-
escrow_address: z.string(),
15-
chain_id: z.number(),
16-
job_type: z.string(),
17-
status: z.string().transform((value) => {
18-
try {
19-
return z.nativeEnum(MyJobStatus).parse(value.toUpperCase());
20-
} catch (error) {
21-
return UNKNOWN_JOB_STATUS;
22-
}
23-
}),
24-
reward_amount: z.string(),
25-
reward_token: z.string(),
26-
created_at: z.string(),
27-
expires_at: z.string(),
28-
url: z.string().optional().nullable(),
29-
});
30-
31-
const myJobsSuccessResponseSchema = createPaginationSchema(myJobSchema);
32-
33-
export type MyJob = z.infer<typeof myJobSchema>;
34-
export type MyJobsSuccessResponse = z.infer<typeof myJobsSuccessResponseSchema>;
35-
export interface MyJobsWithJobTypes {
36-
jobTypes: string[];
37-
jobs: MyJobsSuccessResponse;
38-
}
7+
import { myJobsSuccessResponseSchema } from '../my-jobs/schemas';
8+
import {
9+
useMyJobsFilterStore,
10+
type MyJobsFilterStoreProps,
11+
} from './use-my-jobs-filter-store';
3912

4013
type GetMyJobTableDataDto = MyJobsFilterStoreProps['filterParams'] & {
4114
oracle_address: string;

packages/apps/human-app/frontend/src/modules/worker/jobs/jobs.page.tsx

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -114,19 +114,17 @@ export function JobsPage() {
114114
backgroundColor: isMobile ? 'transparent' : undefined,
115115
}}
116116
>
117-
<div>
118-
{!isError && (
119-
<Box
120-
sx={{
121-
padding: '8px 42px',
122-
backgroundColor: isDarkMode ? '#CDC7FF14' : '#1406B20A',
123-
display: 'inline-block',
124-
}}
125-
>
126-
<Typography variant="h6">{oracleName}</Typography>
127-
</Box>
128-
)}
129-
</div>
117+
{!isError && (
118+
<Box
119+
sx={{
120+
padding: '8px 42px',
121+
backgroundColor: isDarkMode ? '#CDC7FF14' : '#1406B20A',
122+
display: 'inline-block',
123+
}}
124+
>
125+
<Typography variant="h6">{oracleName}</Typography>
126+
</Box>
127+
)}
130128
<Stack>
131129
<TableQueryContextProvider>
132130
<Box sx={{ width: '100%' }}>
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
/* eslint-disable camelcase -- ...*/
2+
import { t } from 'i18next';
3+
import Grid from '@mui/material/Grid';
4+
import { type MRT_ColumnDef } from 'material-react-table';
5+
import RefreshIcon from '@mui/icons-material/Refresh';
6+
import { TableHeaderCell } from '@/shared/components/ui/table/table-header-cell';
7+
import { getNetworkName } from '@/modules/smart-contracts/get-network-name';
8+
import { Button } from '@/shared/components/ui/button';
9+
import { Chip } from '@/shared/components/ui/chip';
10+
import type { JobType } from '@/modules/smart-contracts/EthKVStore/config';
11+
import { formatDate } from '@/shared/helpers/date';
12+
import {
13+
EvmAddress,
14+
RewardAmount,
15+
MyJobsTableActions,
16+
} from '../../../components';
17+
import { type MyJob } from '../../schemas';
18+
import { StatusChip } from './status-chip';
19+
import { MyJobsExpiresAtSort } from './my-jobs-expires-at-sort';
20+
import { MyJobsJobTypeFilter } from './my-jobs-job-type-filter';
21+
import { MyJobsNetworkFilter } from './my-jobs-network-filter';
22+
import { MyJobsRewardAmountSort } from './my-jobs-reward-amount-sort';
23+
import { MyJobsStatusFilter } from './my-jobs-status-filter';
24+
25+
export const getColumnsDefinition = ({
26+
refreshData,
27+
isRefreshTasksPending,
28+
chainIdsEnabled,
29+
}: {
30+
refreshData: () => void;
31+
isRefreshTasksPending: boolean;
32+
chainIdsEnabled: number[];
33+
}): MRT_ColumnDef<MyJob>[] => [
34+
{
35+
accessorKey: 'escrow_address',
36+
header: t('worker.jobs.escrowAddress'),
37+
size: 100,
38+
enableSorting: true,
39+
Cell: (props) => {
40+
return <EvmAddress address={props.row.original.escrow_address} />;
41+
},
42+
},
43+
{
44+
accessorKey: 'network',
45+
header: t('worker.jobs.network'),
46+
size: 100,
47+
Cell: (props) => {
48+
return getNetworkName(props.row.original.chain_id);
49+
},
50+
muiTableHeadCellProps: () => ({
51+
component: (props) => {
52+
return (
53+
<TableHeaderCell
54+
{...props}
55+
headerText={t('worker.jobs.network')}
56+
iconType="filter"
57+
popoverContent={
58+
<MyJobsNetworkFilter chainIdsEnabled={chainIdsEnabled} />
59+
}
60+
/>
61+
);
62+
},
63+
}),
64+
},
65+
{
66+
accessorKey: 'reward_amount',
67+
header: t('worker.jobs.rewardAmount'),
68+
size: 100,
69+
enableSorting: true,
70+
Cell: (props) => {
71+
const { reward_amount, reward_token } = props.row.original;
72+
return (
73+
<RewardAmount
74+
reward_amount={reward_amount}
75+
reward_token={reward_token}
76+
/>
77+
);
78+
},
79+
muiTableHeadCellProps: () => ({
80+
component: (props) => (
81+
<TableHeaderCell
82+
{...props}
83+
headerText={t('worker.jobs.rewardAmount')}
84+
iconType="filter"
85+
popoverContent={<MyJobsRewardAmountSort />}
86+
/>
87+
),
88+
}),
89+
},
90+
{
91+
accessorKey: 'job_type',
92+
header: t('worker.jobs.jobType'),
93+
size: 100,
94+
enableSorting: true,
95+
Cell: ({ row }) => {
96+
const label = t(`jobTypeLabels.${row.original.job_type as JobType}`);
97+
return <Chip label={label} />;
98+
},
99+
muiTableHeadCellProps: () => ({
100+
component: (props) => {
101+
return (
102+
<TableHeaderCell
103+
{...props}
104+
headerText={t('worker.jobs.jobType')}
105+
iconType="filter"
106+
popoverContent={<MyJobsJobTypeFilter />}
107+
/>
108+
);
109+
},
110+
}),
111+
},
112+
{
113+
accessorKey: 'expires_at',
114+
header: t('worker.jobs.expiresAt'),
115+
size: 100,
116+
enableSorting: true,
117+
Cell: (props) => {
118+
return formatDate(props.row.original.expires_at);
119+
},
120+
muiTableHeadCellProps: () => ({
121+
component: (props) => {
122+
return (
123+
<TableHeaderCell
124+
{...props}
125+
headerText={t('worker.jobs.expiresAt')}
126+
iconType="filter"
127+
popoverContent={<MyJobsExpiresAtSort />}
128+
/>
129+
);
130+
},
131+
}),
132+
},
133+
{
134+
accessorKey: 'status',
135+
header: t('worker.jobs.status'),
136+
size: 100,
137+
enableSorting: true,
138+
Cell: (props) => {
139+
const status = props.row.original.status;
140+
return <StatusChip status={status} />;
141+
},
142+
muiTableHeadCellProps: () => ({
143+
component: (props) => {
144+
return (
145+
<TableHeaderCell
146+
{...props}
147+
headerText={t('worker.jobs.status')}
148+
iconType="filter"
149+
popoverContent={<MyJobsStatusFilter />}
150+
/>
151+
);
152+
},
153+
}),
154+
},
155+
{
156+
accessorKey: 'assignment_id',
157+
header: t('worker.jobs.refresh'),
158+
size: 100,
159+
enableSorting: true,
160+
Cell: (props) => (
161+
<Grid sx={{ display: 'flex', justifyContent: 'flex-end', gap: '1rem' }}>
162+
<MyJobsTableActions job={props.row.original} />
163+
</Grid>
164+
),
165+
muiTableHeadCellProps: () => ({
166+
component: (props) => {
167+
return (
168+
<td {...props}>
169+
<Grid
170+
sx={{
171+
display: 'flex',
172+
justifyContent: 'flex-end',
173+
width: '100%',
174+
}}
175+
>
176+
<Button
177+
size="small"
178+
sx={{
179+
paddingTop: '0.4rem',
180+
paddingBottom: '0.4rem',
181+
paddingInline: '1rem',
182+
fontSize: '13px',
183+
}}
184+
loading={isRefreshTasksPending}
185+
type="button"
186+
variant="outlined"
187+
onClick={refreshData}
188+
>
189+
{t('worker.jobs.refresh')}
190+
<RefreshIcon sx={{ marginLeft: '0.5rem' }} />
191+
</Button>
192+
</Grid>
193+
</td>
194+
);
195+
},
196+
}),
197+
},
198+
];

0 commit comments

Comments
 (0)