Skip to content

Commit 9bbe821

Browse files
committed
Add list of my applications
1 parent 040846e commit 9bbe821

File tree

7 files changed

+268
-76
lines changed

7 files changed

+268
-76
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
[
2+
{
3+
"inputs": [],
4+
"name": "gigsGetMyApplications",
5+
"outputs": [
6+
{
7+
"components": [
8+
{
9+
"internalType": "address",
10+
"name": "jobAddress",
11+
"type": "address"
12+
},
13+
{
14+
"internalType": "address",
15+
"name": "applicationAddress",
16+
"type": "address"
17+
},
18+
{
19+
"internalType": "address",
20+
"name": "contractAddress",
21+
"type": "address"
22+
},
23+
{
24+
"internalType": "address",
25+
"name": "applicantAddress",
26+
"type": "address"
27+
},
28+
{
29+
"internalType": "bool",
30+
"name": "hasContract",
31+
"type": "bool"
32+
},
33+
{
34+
"internalType": "string",
35+
"name": "jobTitle",
36+
"type": "string"
37+
},
38+
{
39+
"internalType": "string",
40+
"name": "jobDescription",
41+
"type": "string"
42+
},
43+
{
44+
"internalType": "string",
45+
"name": "applicationComment",
46+
"type": "string"
47+
},
48+
{
49+
"internalType": "string",
50+
"name": "jobCategoryCode",
51+
"type": "string"
52+
},
53+
{
54+
"internalType": "string",
55+
"name": "jobCategoryLabel",
56+
"type": "string"
57+
},
58+
{
59+
"internalType": "uint256",
60+
"name": "jobBudget",
61+
"type": "uint256"
62+
},
63+
{
64+
"internalType": "uint256",
65+
"name": "applicationServiceFee",
66+
"type": "uint256"
67+
},
68+
{
69+
"internalType": "uint64",
70+
"name": "applicationCreatedAt",
71+
"type": "uint64"
72+
}
73+
],
74+
"internalType": "struct GigsMyApplicationValue[]",
75+
"name": "applications",
76+
"type": "tuple[]"
77+
}
78+
],
79+
"stateMutability": "view",
80+
"type": "function"
81+
}
82+
]

src/components/ApplicationListItem.jsx

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/components/ApplicationsList.jsx

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/components/Menu.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const MenuComponent = ({
6262
<Dropdown item text="Freelancer">
6363
<Dropdown.Menu>
6464
<Link href="/freelancer/applications" passHref>
65-
<Dropdown.Item text="My Applications" disabled />
65+
<Dropdown.Item text="My Applications" />
6666
</Link>
6767
<Link href="/freelancer/contracts" passHref>
6868
<Dropdown.Item text="My Contracts" />
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import React from 'react'
2+
import Link from 'next/link'
3+
import { Header, Divider, Label, Icon } from 'semantic-ui-react'
4+
import { formatDateTime } from '../../lib/formatDate'
5+
6+
export const ApplicationListItem = ({ application }) => {
7+
const {
8+
jobBudget,
9+
applicationServiceFee,
10+
jobCategoryLabel,
11+
hasContract,
12+
contractAddress,
13+
} = application
14+
const applicationCreatedAt = formatDateTime(application.applicationCreatedAt)
15+
16+
return (
17+
<>
18+
<Header as="h3" style={{ wordWrap: 'break-word' }}>
19+
<Link href={`/jobs/${application.jobAddress}`}>
20+
{application.jobTitle}
21+
</Link>
22+
</Header>
23+
24+
<Header as="h4">Job Description Preview:</Header>
25+
26+
<div style={{ wordWrap: 'break-word' }}>
27+
{application.jobDescription
28+
.trim()
29+
.split('\n')
30+
.map((str, idx) => {
31+
if (idx < 5) {
32+
return (
33+
<div key={idx}>
34+
{str}
35+
36+
<br />
37+
</div>
38+
)
39+
}
40+
})}
41+
</div>
42+
43+
<Header as="h4">Comment:</Header>
44+
45+
<div style={{ wordWrap: 'break-word' }}>
46+
{application.applicationComment.trim()}
47+
</div>
48+
49+
<Divider />
50+
51+
{jobBudget && jobBudget > 0 && (
52+
<Label>
53+
<Icon name="money bill alternate" title="Job budget" /> {jobBudget}
54+
</Label>
55+
)}
56+
57+
<Label>
58+
<Icon name="money bill alternate outline" title="Service rate" />
59+
{' ' + applicationServiceFee}
60+
</Label>
61+
62+
<Label>
63+
<Icon name="list" /> {jobCategoryLabel}
64+
</Label>
65+
66+
<Label>
67+
<Icon name="clock" title="Application created at" />
68+
{' ' + applicationCreatedAt}
69+
</Label>
70+
71+
{hasContract && (
72+
<Label as="a" href={`/contracts/${contractAddress}`} color="green">
73+
<Icon name="browser" title="Has contract" /> Open contract
74+
</Label>
75+
)}
76+
</>
77+
)
78+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react'
2+
import { Segment, Grid } from 'semantic-ui-react'
3+
import { ApplicationListItem } from './ApplicationListItem'
4+
5+
export const MyApplicationsList = ({ applications }) => {
6+
return (
7+
<Grid columns={1}>
8+
{applications.length > 0 ? (
9+
<>
10+
{applications.map((application) => {
11+
return (
12+
<Grid.Column key={application.address}>
13+
<Segment>
14+
<ApplicationListItem application={application} />
15+
</Segment>
16+
</Grid.Column>
17+
)
18+
})}
19+
</>
20+
) : (
21+
<Grid.Column>
22+
<Segment>
23+
<p>No applications yet</p>
24+
</Segment>
25+
</Grid.Column>
26+
)}
27+
</Grid>
28+
)
29+
}
Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,82 @@
1-
import React from 'react'
2-
import { Container, Header } from 'semantic-ui-react'
1+
import React, { useState, useEffect } from 'react'
2+
import { ethers } from 'ethers'
3+
import getConfig from 'next/config'
4+
import { Grid, Header } from 'semantic-ui-react'
5+
import { MyApplicationsList } from '../../../../components/MyApplicationsList'
6+
import { useContractRead } from 'wagmi'
7+
8+
import gigsGetMyApplicationsQueryABI from '../../../../../contracts/GigsGetMyApplicationsQuery.json'
9+
import { JustOneSecondBlockchain } from '../../../../components/JustOneSecond'
10+
import { errorHandler } from '../../../../lib/errorHandler'
11+
import ErrorWrapper from '../../../../components/ErrorWrapper'
12+
13+
const { publicRuntimeConfig } = getConfig()
14+
const { optriSpaceContractAddress } = publicRuntimeConfig
15+
16+
export const ApplicationsScreen = ({ currentAccount }) => {
17+
const {
18+
data: rawApplications,
19+
error: applicationsError,
20+
isLoading: applicationsLoading,
21+
} = useContractRead({
22+
address: optriSpaceContractAddress,
23+
abi: gigsGetMyApplicationsQueryABI,
24+
functionName: 'gigsGetMyApplications',
25+
overrides: { from: currentAccount },
26+
})
27+
28+
const [applications, setApplications] = useState(undefined)
29+
30+
// FIXME: It should be replaced with: https://wagmi.sh/react/hooks/useContractRead#select-optional
31+
useEffect(() => {
32+
if (!rawApplications) return
33+
34+
const j = rawApplications.map((application) => {
35+
return {
36+
address: application.applicationAddress,
37+
jobAddress: application.jobAddress,
38+
contractAddress: application.contractAddress,
39+
hasContract: application.hasContract,
40+
jobTitle: application.jobTitle,
41+
jobDescription: application.jobDescription,
42+
applicationComment: application.applicationComment,
43+
jobCategoryCode: application.jobCategoryCode,
44+
jobCategoryLabel: application.jobCategoryLabel,
45+
jobBudget: ethers.utils.formatEther(application.jobBudget.toString()),
46+
applicationServiceFee: ethers.utils.formatEther(
47+
application.applicationServiceFee.toString()
48+
),
49+
applicationCreatedAt: +application.applicationCreatedAt.toString(),
50+
}
51+
})
52+
53+
const orderedApplications = j.slice().sort((a, b) => {
54+
return +b.applicationCreatedAt - +a.applicationCreatedAt
55+
})
56+
57+
setApplications(orderedApplications)
58+
}, [rawApplications])
359

4-
export const ApplicationsScreen = () => {
560
return (
6-
<Container textAlign="center">
7-
<Header as="h1" content="My applications will be available later" />
8-
</Container>
61+
<Grid stackable columns={1}>
62+
<Grid.Column textAlign="center">
63+
<Header as="h1" content="My Applications" />
64+
</Grid.Column>
65+
66+
<Grid.Column>
67+
{applicationsLoading && (
68+
<JustOneSecondBlockchain message="Fetching applications from the blockchain..." />
69+
)}
70+
71+
{applicationsError && (
72+
<ErrorWrapper
73+
header="Error fetching applications"
74+
error={errorHandler(applicationsError)}
75+
/>
76+
)}
77+
78+
{applications && <MyApplicationsList applications={applications} />}
79+
</Grid.Column>
80+
</Grid>
981
)
1082
}

0 commit comments

Comments
 (0)