Skip to content

Commit ef198d2

Browse files
authored
Merge pull request #264 from CivicDataLab/263-add-publishers-page
263 add publishers page
2 parents 0c05620 + 3528030 commit ef198d2

File tree

15 files changed

+1069
-6
lines changed

15 files changed

+1069
-6
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import Image from 'next/image';
2+
import Link from 'next/link';
3+
import { Text } from 'opub-ui';
4+
import React from 'react';
5+
6+
7+
interface CardProps {
8+
data: any;
9+
}
10+
11+
const PublisherCard: React.FC<CardProps> = ({ data }) => {
12+
return (
13+
<div className="my-10">
14+
<div className=" grid w-full grid-cols-1 gap-10 md:grid-cols-2 lg:grid-cols-3 lg:gap-16">
15+
{data.map((item: any, index: any) => (
16+
<Link
17+
href={
18+
item.__typename === 'TypeOrganization'
19+
? `/publishers/organization/${item.id}`
20+
: `/publishers/${item.id}`
21+
}
22+
key={index}
23+
className="flex flex-col gap-4 rounded-4 p-6 shadow-card"
24+
>
25+
<div className="flex items-center gap-4">
26+
<Image
27+
height={80}
28+
width={80}
29+
src={
30+
item.__typename === 'TypeUser'
31+
? item?.profilePicture
32+
? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${item.profilePicture.url}`
33+
: '/profile.png'
34+
: item?.logo
35+
? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${item.logo.url}`
36+
: '/org.png'
37+
}
38+
alt={'logo'}
39+
className=" rounded-2 border-2 border-solid border-greyExtralight object-contain p-2"
40+
/>
41+
<div className="flex flex-col gap-2">
42+
<Text className=" text-primaryBlue" fontWeight="semibold">
43+
{item.__typename === 'TypeUser' ? item.fullName : item.name}
44+
</Text>
45+
<div className=" flex w-fit rounded-full border-1 border-solid border-[#D5E1EA] bg-[#E9EFF4] px-3 py-1">
46+
<Text variant="bodySm">
47+
{item.__typename === 'TypeUser'
48+
? 'Individual Publisher'
49+
: 'Organization'}
50+
</Text>
51+
</div>
52+
</div>
53+
</div>
54+
<div className="flex flex-wrap gap-3">
55+
<div className=" flex w-fit rounded-full border-1 border-solid border-[#D5E1EA] px-3 py-1">
56+
<Text variant="bodySm" className=" text-primaryBlue">
57+
{item.publishedUseCasesCount} Use Cases
58+
</Text>
59+
</div>
60+
<div className=" flex w-fit rounded-full border-1 border-solid border-[#D5E1EA] px-3 py-1">
61+
<Text variant="bodySm" className=" text-primaryBlue">
62+
{item.publishedDatasetsCount} Datasets
63+
</Text>
64+
</div>
65+
<div className=" flex w-fit rounded-full border-1 border-solid border-[#D5E1EA] px-3 py-1">
66+
<Text variant="bodySm" className=" text-primaryBlue">
67+
3 Followers{' '}
68+
</Text>
69+
</div>
70+
</div>
71+
</Link>
72+
))}
73+
</div>
74+
</div>
75+
);
76+
};
77+
78+
export default PublisherCard;
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
'use client';
2+
3+
import React from 'react';
4+
import { useParams } from 'next/navigation';
5+
import { graphql } from '@/gql';
6+
import { useQuery } from '@tanstack/react-query';
7+
import { Spinner } from 'opub-ui';
8+
9+
import { GraphQL } from '@/lib/api';
10+
import BreadCrumbs from '@/components/BreadCrumbs';
11+
import ProfileDetails from '../components/ProfileDetails';
12+
import SidebarCard from '../components/SidebarCard';
13+
14+
const userInfoQuery: any = graphql(`
15+
query UserData($userId: ID!) {
16+
userById(userId: $userId) {
17+
id
18+
bio
19+
dateJoined
20+
contributedSectorsCount
21+
location
22+
twitterProfile
23+
githubProfile
24+
fullName
25+
profilePicture {
26+
url
27+
}
28+
publishedUseCasesCount
29+
publishedDatasetsCount
30+
linkedinProfile
31+
}
32+
}
33+
`);
34+
35+
const PublisherPage = () => {
36+
const params = useParams();
37+
const userInfo: any = useQuery([`${params.publisherSlug}`], () =>
38+
GraphQL(
39+
userInfoQuery,
40+
{
41+
// Entity Headers if present
42+
},
43+
{ userId: params.publisherSlug }
44+
)
45+
);
46+
47+
return (
48+
<main className="bg-primaryBlue">
49+
<BreadCrumbs
50+
data={[
51+
{ href: '/', label: 'Home' },
52+
{ href: '/publishers', label: 'Publishers' },
53+
{ href: '#', label: `${userInfo?.data?.userById?.fullName || ''} ` },
54+
]}
55+
/>
56+
{
57+
<div className="container py-10 text-surfaceDefault">
58+
<div className="flex flex-wrap gap-10 lg:flex-nowrap">
59+
<div className="w-full lg:w-1/4">
60+
{userInfo?.isLoading ? (
61+
<div className="m-4 flex justify-center rounded-2 bg-surfaceDefault p-4">
62+
<Spinner color="highlight" />
63+
</div>
64+
) : (
65+
<SidebarCard data={userInfo?.data?.userById} type="Publisher" />
66+
)}
67+
</div>
68+
<div className="w-full">
69+
{userInfo?.isLoading ? (
70+
<div className="m-4 flex justify-center rounded-2 bg-surfaceDefault p-4">
71+
<Spinner color="highlight" />
72+
</div>
73+
) : (
74+
<ProfileDetails data={userInfo?.data?.userById} type="Publisher" />
75+
)}
76+
</div>
77+
</div>
78+
</div>
79+
}
80+
</main>
81+
);
82+
};
83+
84+
export default PublisherPage;
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
import { useParams } from 'next/navigation';
2+
import { graphql } from '@/gql';
3+
import { useQuery } from '@tanstack/react-query';
4+
import { Card, Spinner } from 'opub-ui';
5+
6+
import { GraphQL } from '@/lib/api';
7+
import { cn } from '@/lib/utils';
8+
import { Icons } from '@/components/icons';
9+
10+
const userPublishedDatasetsDoc: any = graphql(`
11+
query userPublishedDatasetsList($userId: ID!) {
12+
userPublishedDatasets(userId: $userId) {
13+
id
14+
title
15+
downloadCount
16+
id
17+
title
18+
tags {
19+
id
20+
value
21+
}
22+
description
23+
created
24+
modified
25+
isIndividualDataset
26+
user {
27+
fullName
28+
id
29+
profilePicture {
30+
url
31+
}
32+
}
33+
metadata {
34+
metadataItem {
35+
id
36+
label
37+
dataType
38+
}
39+
value
40+
}
41+
organization {
42+
name
43+
logo {
44+
url
45+
}
46+
slug
47+
id
48+
}
49+
sectors {
50+
name
51+
}
52+
formats
53+
}
54+
}
55+
`);
56+
57+
const organizationPublishedDatasetsDoc: any = graphql(`
58+
query organizationPublishedDatasetsList($organizationId: ID!) {
59+
organizationPublishedDatasets(organizationId: $organizationId) {
60+
id
61+
title
62+
downloadCount
63+
id
64+
title
65+
tags {
66+
id
67+
value
68+
}
69+
description
70+
created
71+
modified
72+
isIndividualDataset
73+
user {
74+
fullName
75+
id
76+
profilePicture {
77+
url
78+
}
79+
}
80+
metadata {
81+
metadataItem {
82+
id
83+
label
84+
dataType
85+
}
86+
value
87+
}
88+
organization {
89+
name
90+
logo {
91+
url
92+
}
93+
slug
94+
id
95+
}
96+
sectors {
97+
name
98+
}
99+
formats
100+
}
101+
}
102+
`);
103+
104+
const Datasets = ({ type }: { type: 'organization' | 'Publisher' }) => {
105+
const params = useParams();
106+
107+
const PublishedDatasetsList: any = useQuery(
108+
[`userDataset_${params.publisherSlug}`],
109+
() =>
110+
type === 'organization'
111+
? GraphQL(
112+
organizationPublishedDatasetsDoc,
113+
{
114+
// Entity Headers
115+
},
116+
{ organizationId: params.organizationSlug } // ✅ exact match for expected shape
117+
)
118+
: GraphQL(
119+
userPublishedDatasetsDoc,
120+
{
121+
// Entity Headers
122+
},
123+
{ userId: params.publisherSlug } // ✅ exact match for expected shape
124+
)
125+
);
126+
127+
const DatasetData =
128+
type === 'organization'
129+
? PublishedDatasetsList.data?.organizationPublishedDatasets
130+
: PublishedDatasetsList.data?.userPublishedDatasets;
131+
132+
return (
133+
<div>
134+
<div
135+
className={cn(
136+
'grid w-full grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-2'
137+
)}
138+
>
139+
{PublishedDatasetsList.isLoading ? (
140+
<div className=" mt-8 flex justify-center">
141+
<Spinner />
142+
</div>
143+
) : (
144+
DatasetData?.length > 0 &&
145+
DatasetData?.map((item: any, index: any) => (
146+
<Card
147+
type={[
148+
{
149+
label: 'Dataset',
150+
fillColor: '#E9EFF4',
151+
borderColor: '#F9C74F',
152+
},
153+
]}
154+
key={index}
155+
title={item.title}
156+
description={item.description}
157+
metadataContent={[
158+
{
159+
icon: Icons.calendar,
160+
label: 'Date',
161+
value: '19 July 2024',
162+
},
163+
{
164+
icon: Icons.download,
165+
label: 'Download',
166+
value: item.downloadCount.toString(),
167+
},
168+
{
169+
icon: Icons.globe,
170+
label: 'Geography',
171+
value: 'India',
172+
},
173+
]}
174+
tag={item.tags}
175+
formats={item.formats}
176+
footerContent={[
177+
{
178+
icon: `/Sectors/${item.sectors[0].name}.svg`,
179+
label: 'Sectors',
180+
},
181+
{
182+
icon: item.isIndividualDataset
183+
? item?.user?.profilePicture
184+
? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${item.user.profilePicture.url}`
185+
: '/profile.png'
186+
: item?.organization?.logo
187+
? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${item.organization.logo.url}`
188+
: '/org.png',
189+
label: 'Published by',
190+
},
191+
]}
192+
variation={'collapsed'}
193+
iconColor="warning"
194+
href={`/datasets/${item.id}`}
195+
/>
196+
))
197+
)}
198+
</div>
199+
</div>
200+
);
201+
};
202+
203+
export default Datasets;

0 commit comments

Comments
 (0)