Skip to content

Commit 5aae6b7

Browse files
committed
Implemented a status verification icon
Created a verification badge by instantianting it in a React component and its story, which is called in the AppHeader component. Declared a corresponding function in the fetchers file, which fetches the URL of the verification status from the env file. Signed-off-by: Mihai State <mihai.state@codethink.co.uk> Co-authored-by: Kolja Lampe <razzeee@gmail.com>
1 parent 6e3e988 commit 5aae6b7

File tree

13 files changed

+158
-15
lines changed

13 files changed

+158
-15
lines changed

frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"react-copy-to-clipboard": "^5.1.0",
3232
"react-country-flag": "^3.0.2",
3333
"react-dom": "^17.0.2",
34-
"react-icons": "^4.4.0",
34+
"react-icons": "^4.6.0",
3535
"react-image-lightbox": "^5.1.4",
3636
"react-responsive-carousel": "^3.2.23",
3737
"react-svg-worldmap": "^2.0.0-alpha.0",

frontend/pages/apps/details/[appDetails].tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
fetchSummary,
99
fetchDeveloperApps,
1010
fetchProjectgroupApps,
11+
fetchVerificationStatus,
1112
} from "../../../src/fetchers"
1213
import { NextSeo } from "next-seo"
1314
import {
@@ -17,19 +18,22 @@ import {
1718
} from "../../../src/types/Appstream"
1819
import { Summary } from "../../../src/types/Summary"
1920
import { AppStats } from "../../../src/types/AppStats"
21+
import { VerificationStatus } from "src/types/VerificationStatus"
2022

2123
export default function Details({
2224
app,
2325
summary,
2426
stats,
2527
developerApps,
2628
projectgroupApps,
29+
verificationStatus,
2730
}: {
2831
app: Appstream
2932
summary?: Summary
3033
stats: AppStats
3134
developerApps: Appstream[]
3235
projectgroupApps: Appstream[]
36+
verificationStatus: VerificationStatus
3337
}) {
3438
const screenshots = app.screenshots
3539
? app.screenshots.filter(pickScreenshot).map((screenshot: Screenshot) => ({
@@ -59,6 +63,7 @@ export default function Details({
5963
projectgroupApps={projectgroupApps.filter(
6064
(devApp) => devApp.id !== app.id,
6165
)}
66+
verificationStatus={verificationStatus}
6267
/>
6368
</>
6469
)
@@ -74,6 +79,7 @@ export const getStaticProps: GetStaticProps = async ({
7479
const stats = await fetchAppStats(appId as string)
7580
const developerApps = await fetchDeveloperApps(app?.developer_name)
7681
const projectgroupApps = await fetchProjectgroupApps(app?.project_group)
82+
const verificationStatus = await fetchVerificationStatus(appId as string)
7783

7884
return {
7985
props: {
@@ -83,6 +89,7 @@ export const getStaticProps: GetStaticProps = async ({
8389
stats,
8490
developerApps: developerApps ?? [],
8591
projectgroupApps: projectgroupApps ?? [],
92+
verificationStatus,
8693
},
8794
revalidate: 3600,
8895
}

frontend/public/locales/en/common.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,5 +251,7 @@
251251
"your-profile": "Your Profile",
252252
"show-more": "Show More",
253253
"show-less": "Show Less",
254-
"more-type": "More {{type}}"
254+
"more-type": "More {{type}}",
255+
"verified": "Verified",
256+
"app-is-verified": "This app is verified."
255257
}

frontend/src/components/application/AppHeader.stories.tsx

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import React from "react"
22
import { ComponentMeta } from "@storybook/react"
33
import { faker } from "@faker-js/faker"
44
import { AppHeader } from "./AppHeader"
5-
import { Appstream } from "src/types/Appstream"
6-
import { VendingSetup } from "src/types/Vending"
5+
import { Appstream } from "../../../src/types/Appstream"
6+
import { VendingSetup } from "../../../src/types/Vending"
77

88
export default {
99
title: "Components/Application/AppHeader",
@@ -32,6 +32,34 @@ export const Install = () => {
3232
installClicked={() => {}}
3333
donateClicked={() => {}}
3434
vendingSetup={undefined}
35+
verificationStatus={{ verified: true }}
36+
/>
37+
)
38+
}
39+
40+
export const InstallNotVerified = () => {
41+
const app = {
42+
id: faker.datatype.uuid(),
43+
icon: faker.image.image(),
44+
name: faker.commerce.product(),
45+
developer_name: faker.internet.userName(),
46+
}
47+
48+
const user = {
49+
loading: false,
50+
info: {
51+
"dev-flatpaks": [],
52+
},
53+
}
54+
55+
return (
56+
<AppHeader
57+
app={app}
58+
user={user}
59+
installClicked={() => {}}
60+
donateClicked={() => {}}
61+
vendingSetup={undefined}
62+
verificationStatus={{ verified: false }}
3563
/>
3664
)
3765
}
@@ -59,6 +87,7 @@ export const InstallWithDonate = () => {
5987
installClicked={() => {}}
6088
donateClicked={() => {}}
6189
vendingSetup={undefined}
90+
verificationStatus={{ verified: true }}
6291
/>
6392
)
6493
}
@@ -87,6 +116,7 @@ export const UserOwnsApp = () => {
87116
installClicked={() => {}}
88117
donateClicked={() => {}}
89118
vendingSetup={undefined}
119+
verificationStatus={{ verified: true }}
90120
/>
91121
)
92122
}
@@ -119,6 +149,7 @@ export const WithVending = () => {
119149
installClicked={() => {}}
120150
donateClicked={() => {}}
121151
vendingSetup={vending}
152+
verificationStatus={{ verified: true }}
122153
/>
123154
)
124155
}

frontend/src/components/application/AppHeader.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
11
import { useTranslation } from "next-i18next"
2-
import Link from "next/link"
32
import React from "react"
43
import { Appstream } from "src/types/Appstream"
54
import { UserState } from "src/types/Login"
65
import { VendingSetup } from "src/types/Vending"
6+
import { VerificationStatus } from "src/types/VerificationStatus"
77
import Button from "../Button"
88
import ButtonLink from "../ButtonLink"
99
import LogoImage from "../LogoImage"
10+
import Verification from "./Verification"
1011

1112
export function AppHeader({
1213
app,
1314
user,
1415
installClicked,
1516
donateClicked,
1617
vendingSetup,
18+
verificationStatus,
1719
}: {
1820
app: Appstream
1921
user: UserState
2022
installClicked: (e: any) => void
2123
donateClicked: (e: any) => void
2224
vendingSetup: VendingSetup
25+
verificationStatus: VerificationStatus
2326
}) {
2427
const { t } = useTranslation()
2528

@@ -32,7 +35,10 @@ export function AppHeader({
3235
)}
3336

3437
<div className="mx-3 my-auto">
35-
<h2 className="mt-0 mb-3">{app.name}</h2>
38+
<div className="mb-3 flex space-x-4">
39+
<h2 className="my-0">{app.name}</h2>
40+
<Verification verificationStatus={verificationStatus}></Verification>
41+
</div>
3642
{app.developer_name?.trim().length > 0 && (
3743
<div className="text-sm font-light">
3844
{t("by", {

frontend/src/components/application/Details.stories.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import React from "react"
22
import { ComponentMeta } from "@storybook/react"
33
import Details from "./Details"
44
import { faker } from "@faker-js/faker"
5-
import { AppStats } from "src/types/AppStats"
6-
import { Appstream } from "src/types/Appstream"
7-
import { Summary } from "src/types/Summary"
5+
import { AppStats } from "../../types/AppStats"
6+
import { Appstream } from "../../types/Appstream"
7+
import { Summary } from "../../types/Summary"
88

99
export default {
1010
title: "Components/Application/Details",
@@ -42,7 +42,7 @@ export const Generated = () => {
4242
}
4343

4444
const app: Appstream = {
45-
id: faker.datatype.number(),
45+
id: faker.datatype.number().toString(),
4646
releases: [
4747
{
4848
version: faker.datatype.number().toString(),
@@ -62,6 +62,7 @@ export const Generated = () => {
6262
stats={stats}
6363
developerApps={developerApps}
6464
projectgroupApps={projectgroupApps}
65+
verificationStatus={{ verified: true }}
6566
/>
6667
)
6768
}

frontend/src/components/application/Details.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@ import { useAsync } from "../../hooks/useAsync"
3434
import { getAppVendingSetup } from "../../asyncs/vending"
3535

3636
import useCollapse from "react-collapsed"
37+
import { VerificationStatus } from "src/types/VerificationStatus"
3738

3839
interface Props {
3940
app?: Appstream
4041
summary?: Summary
4142
stats: AppStats
4243
developerApps: Appstream[]
4344
projectgroupApps: Appstream[]
45+
verificationStatus: VerificationStatus
4446
}
4547

4648
function categoryToSeoCategories(categories: string[]) {
@@ -82,6 +84,7 @@ const Details: FunctionComponent<Props> = ({
8284
stats,
8385
developerApps,
8486
projectgroupApps,
87+
verificationStatus,
8588
}) => {
8689
const { t } = useTranslation()
8790
const user = useUserContext()
@@ -152,6 +155,7 @@ const Details: FunctionComponent<Props> = ({
152155
installClicked={installClicked}
153156
donateClicked={donateClicked}
154157
vendingSetup={vendingSetup}
158+
verificationStatus={verificationStatus}
155159
/>
156160
<div className="col-start-1 col-end-4 bg-bgColorSecondary">
157161
{showLightbox && (
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from "react"
2+
import { ComponentMeta } from "@storybook/react"
3+
import Verification from "./Verification"
4+
import { VerificationStatus } from "../../types/VerificationStatus"
5+
export default {
6+
title: "Components/Application/Verification",
7+
component: Verification,
8+
} as ComponentMeta<typeof Verification>
9+
10+
export const Generated = () => {
11+
const verificationStatus: VerificationStatus = { verified: true }
12+
return <Verification verificationStatus={verificationStatus} />
13+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { FunctionComponent } from "react"
2+
import React from "react"
3+
4+
import { HiCheckBadge } from "react-icons/hi2"
5+
import { useTranslation } from "next-i18next"
6+
import { VerificationStatus } from "src/types/VerificationStatus"
7+
8+
interface Props {
9+
verificationStatus: VerificationStatus
10+
}
11+
12+
const Verification: FunctionComponent<Props> = ({ verificationStatus }) => {
13+
const { t } = useTranslation()
14+
15+
if (verificationStatus?.verified == true) {
16+
return (
17+
<HiCheckBadge
18+
className="h-10 w-10 text-colorPrimary"
19+
title={t("verified")}
20+
aria-label={t("app-is-verified")}
21+
/>
22+
)
23+
} else {
24+
return null
25+
}
26+
}
27+
export default Verification

frontend/src/env.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,6 @@ export const IS_PRODUCTION: boolean =
104104
export const STRIPE_MAX_PAYMENT = 999999.99
105105
// Flathub enforces a minimum payment amount of $1 to cover fees
106106
export const FLATHUB_MIN_PAYMENT = 1
107+
108+
export const APP_VERIFICATION_STATUS = (id: string): string =>
109+
`${BASE_URI}/verification/${id}/status`

0 commit comments

Comments
 (0)