Skip to content

Commit eceaded

Browse files
committed
add ability to add usecase and fix usecase card
1 parent e0cc4f1 commit eceaded

File tree

4 files changed

+283
-59
lines changed

4 files changed

+283
-59
lines changed

app/[locale]/(user)/collaboratives/[collaborativeSlug]/CollaborativeDetailsClient.tsx

Lines changed: 78 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
'use client';
22

3+
import { graphql } from '@/gql';
4+
import { TypeCollaborative, TypeDataset, TypeUseCase } from '@/gql/generated/graphql';
5+
import { useQuery } from '@tanstack/react-query';
36
import Image from 'next/image';
47
import Link from 'next/link';
58
import { useParams } from 'next/navigation';
6-
import { useEffect } from 'react';
7-
import { graphql } from '@/gql';
8-
import { TypeDataset, TypeCollaborative, TypeUseCase } from '@/gql/generated/graphql';
9-
import { useQuery } from '@tanstack/react-query';
109
import { Card, Text } from 'opub-ui';
10+
import { useEffect } from 'react';
1111

12-
import { GraphQLPublic } from '@/lib/api';
13-
import { formatDate, generateJsonLd } from '@/lib/utils';
14-
import { useAnalytics } from '@/hooks/use-analytics';
1512
import BreadCrumbs from '@/components/BreadCrumbs';
1613
import { Icons } from '@/components/icons';
1714
import JsonLd from '@/components/JsonLd';
1815
import { Loading } from '@/components/loading';
16+
import { useAnalytics } from '@/hooks/use-analytics';
17+
import { GraphQLPublic } from '@/lib/api';
18+
import { formatDate, generateJsonLd } from '@/lib/utils';
1919
import PrimaryDetails from '../components/Details';
2020
import Metadata from '../components/Metadata';
2121

@@ -418,55 +418,77 @@ const CollaborativeDetailClient = () => {
418418
</Text>
419419
</div>
420420
<div className="grid grid-cols-1 gap-6 pt-10 md:grid-cols-2 lg:grid-cols-3 ">
421-
{useCases.map((useCase: TypeUseCase) => (
422-
<Card
423-
key={useCase.id}
424-
title={useCase.title || ''}
425-
variation={'collapsed'}
426-
iconColor={'success'}
427-
metadataContent={[
428-
{
429-
icon: Icons.calendar,
430-
label: 'Started',
431-
value: formatDate(useCase.startedOn),
432-
},
433-
{
434-
icon: Icons.activity,
435-
label: 'Status',
436-
value: useCase.runningStatus?.split('_').join(' ') || 'N/A',
437-
},
438-
{
439-
icon: Icons.globe,
440-
label: 'Geography',
441-
value:
442-
useCase.metadata?.find(
443-
(meta: any) =>
444-
meta.metadataItem?.label === 'Geography'
445-
)?.value || '',
446-
},
447-
]}
448-
href={`/usecases/${useCase.slug}`}
449-
footerContent={[
450-
{
451-
icon: useCase.sectors && useCase.sectors[0]?.name
452-
? `/Sectors/${useCase.sectors[0].name}.svg`
453-
: '/Sectors/default.svg',
454-
label: 'Sectors',
455-
},
456-
{
457-
icon: useCase.isIndividualUsecase
458-
? useCase?.user?.profilePicture
459-
? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${useCase.user.profilePicture.url}`
460-
: '/profile.png'
461-
: useCase?.organization?.logo
462-
? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${useCase.organization.logo.url}`
463-
: '/org.png',
464-
label: 'Published by',
465-
},
466-
]}
467-
description={useCase.summary || ''}
468-
/>
469-
))}
421+
{useCases.map((useCase: TypeUseCase) => {
422+
const image = useCase.isIndividualUsecase
423+
? useCase?.user?.profilePicture
424+
? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${useCase.user.profilePicture.url}`
425+
: '/profile.png'
426+
: useCase?.organization?.logo
427+
? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${useCase.organization.logo.url}`
428+
: '/org.png';
429+
430+
const Geography = useCase.metadata?.find(
431+
(meta: any) => meta.metadataItem?.label === 'Geography'
432+
)?.value;
433+
434+
const MetadataContent = [
435+
{
436+
icon: Icons.calendar,
437+
label: 'Date',
438+
value: formatDate(useCase.modified),
439+
tooltip: 'Date',
440+
},
441+
];
442+
443+
if (Geography) {
444+
MetadataContent.push({
445+
icon: Icons.globe,
446+
label: 'Geography',
447+
value: Geography,
448+
tooltip: 'Geography',
449+
});
450+
}
451+
452+
const FooterContent = [
453+
{
454+
icon: useCase.sectors && useCase.sectors[0]?.name
455+
? `/Sectors/${useCase.sectors[0].name}.svg`
456+
: '/Sectors/default.svg',
457+
label: 'Sectors',
458+
tooltip: useCase.sectors?.[0]?.name || 'Sector',
459+
},
460+
{
461+
icon: image,
462+
label: 'Published by',
463+
tooltip: useCase.isIndividualUsecase
464+
? useCase.user?.fullName
465+
: useCase.organization?.name,
466+
},
467+
];
468+
469+
const commonProps = {
470+
title: useCase.title || '',
471+
description: useCase.summary || '',
472+
metadataContent: MetadataContent,
473+
tag: useCase.tags?.map((t: any) => t.value) || [],
474+
footerContent: FooterContent,
475+
imageUrl: '',
476+
};
477+
478+
if (useCase.logo) {
479+
commonProps.imageUrl = `${process.env.NEXT_PUBLIC_BACKEND_URL}/${useCase.logo.path.replace('/code/files/', '')}`;
480+
}
481+
482+
return (
483+
<Card
484+
{...commonProps}
485+
key={useCase.id}
486+
variation={'collapsed'}
487+
iconColor="success"
488+
href={`/usecases/${useCase.slug}`}
489+
/>
490+
);
491+
})}
470492
</div>
471493
</div>
472494
)}

app/[locale]/dashboard/[entityType]/[entitySlug]/collaboratives/edit/[id]/publish/page.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ const CollaborativeDetails: any = graphql(`
6666
}
6767
modified
6868
}
69+
useCases {
70+
title
71+
id
72+
slug
73+
sectors {
74+
name
75+
}
76+
modified
77+
}
6978
contactEmail
7079
status
7180
slug
@@ -166,13 +175,18 @@ const Publish = () => {
166175
errorType: 'critical',
167176
},
168177
{
169-
name: 'Assign',
178+
name: 'Datasets',
170179
data: CollaborativeData?.data?.collaboratives[0]?.datasets,
171180
error:
172181
CollaborativeData.data && CollaborativeData.data?.collaboratives[0]?.datasets.length === 0
173182
? 'No datasets assigned. Please assign to continue.'
174183
: '',
175184
},
185+
{
186+
name: 'Use Cases',
187+
data: CollaborativeData?.data?.collaboratives[0]?.useCases,
188+
error: '',
189+
},
176190
{
177191
name: 'Dashboards',
178192
data: CollaborativeData?.data?.collaboratives[0]?.length > 0,
@@ -252,7 +266,9 @@ const Publish = () => {
252266
}}
253267
>
254268
<div className=" py-4">
255-
{item.name === 'Assign' ? (
269+
{item.name === 'Datasets' ? (
270+
<Assign data={item.data} />
271+
) : item.name === 'Use Cases' ? (
256272
<Assign data={item.data} />
257273
) : item.name === 'Details' ? (
258274
<Details data={CollaborativeData.data} />
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
'use client';
2+
3+
import React, { useEffect, useState } from 'react';
4+
import { useParams, useRouter } from 'next/navigation';
5+
import { fetchData } from '@/fetch';
6+
import { graphql } from '@/gql';
7+
import { useMutation, useQuery } from '@tanstack/react-query';
8+
import { Button, DataTable, Text, toast } from 'opub-ui';
9+
10+
import { GraphQL } from '@/lib/api';
11+
import { formatDate } from '@/lib/utils';
12+
import { Loading } from '@/components/loading';
13+
14+
const FetchCollaborativeDetails: any = graphql(`
15+
query CollaborativeUseCaseDetails($filters: CollaborativeFilter) {
16+
collaboratives(filters: $filters) {
17+
id
18+
title
19+
useCases {
20+
id
21+
title
22+
slug
23+
modified
24+
sectors {
25+
name
26+
}
27+
}
28+
}
29+
}
30+
`);
31+
32+
const AssignCollaborativeUseCases: any = graphql(`
33+
mutation assignCollaborativeUseCases($collaborativeId: String!, $useCaseIds: [String!]!) {
34+
updateCollaborativeUseCases(collaborativeId: $collaborativeId, useCaseIds: $useCaseIds) {
35+
... on TypeCollaborative {
36+
id
37+
useCases {
38+
id
39+
title
40+
}
41+
}
42+
}
43+
}
44+
`);
45+
46+
const UseCases = () => {
47+
const params = useParams<{
48+
entityType: string;
49+
entitySlug: string;
50+
id: string;
51+
}>();
52+
const router = useRouter();
53+
54+
const [data, setData] = useState<any[]>([]); // Ensure `data` is an array
55+
const [selectedRow, setSelectedRows] = useState<any[]>([]);
56+
57+
const CollaborativeDetails: { data: any; isLoading: boolean; refetch: any } =
58+
useQuery(
59+
[`Collaborative_UseCase_Details`, params.id],
60+
() =>
61+
GraphQL(
62+
FetchCollaborativeDetails,
63+
{
64+
[params.entityType]: params.entitySlug,
65+
},
66+
{
67+
filters: {
68+
id: params.id,
69+
},
70+
}
71+
),
72+
{
73+
refetchOnMount: true,
74+
refetchOnReconnect: true,
75+
}
76+
);
77+
78+
const formattedData = (data: any) =>
79+
data.map((item: any) => {
80+
return {
81+
title: item.title,
82+
id: item.id,
83+
category: item.sectors[0]?.name || 'N/A', // Safeguard in case of missing category
84+
modified: formatDate(item.modified),
85+
};
86+
});
87+
88+
useEffect(() => {
89+
fetchData('usecase', '?size=1000&page=1')
90+
.then((res) => {
91+
setData(res.results);
92+
})
93+
.catch((err) => {
94+
console.error(err);
95+
});
96+
}, []);
97+
98+
const columns = [
99+
{ accessorKey: 'title', header: 'Title' },
100+
{ accessorKey: 'category', header: 'Sector' },
101+
{ accessorKey: 'modified', header: 'Last Modified' },
102+
];
103+
104+
const generateTableData = (list: Array<any>) => {
105+
return list.map((item) => {
106+
return {
107+
title: item.title,
108+
id: item.id,
109+
category: item.sectors[0],
110+
modified: formatDate(item.modified),
111+
};
112+
});
113+
};
114+
115+
const { mutate, isLoading: mutationLoading } = useMutation(
116+
() =>
117+
GraphQL(
118+
AssignCollaborativeUseCases,
119+
{
120+
[params.entityType]: params.entitySlug,
121+
},
122+
{
123+
collaborativeId: params.id,
124+
useCaseIds: Array.isArray(selectedRow)
125+
? selectedRow.map((row: any) => String(row.id))
126+
: [],
127+
}
128+
),
129+
{
130+
onSuccess: (data: any) => {
131+
toast('Use Cases Assigned Successfully');
132+
CollaborativeDetails.refetch();
133+
router.push(
134+
`/dashboard/${params.entityType}/${params.entitySlug}/collaboratives/edit/${params.id}/contributors`
135+
);
136+
},
137+
onError: (err: any) => {
138+
toast(`Received ${err} on use case assignment`);
139+
},
140+
}
141+
);
142+
143+
return (
144+
<>
145+
{CollaborativeDetails?.data?.collaboratives[0]?.useCases?.length >= 0 &&
146+
data.length > 0 &&
147+
!CollaborativeDetails.isLoading ? (
148+
<>
149+
<div className="flex justify-between">
150+
<div>
151+
<Text>
152+
Selected {selectedRow.length} of {data.length}
153+
</Text>
154+
</div>
155+
<div className="mb-4 flex justify-end">
156+
<Button className="w-fit" onClick={() => mutate()}>
157+
Submit
158+
</Button>
159+
</div>
160+
</div>
161+
162+
<DataTable
163+
columns={columns}
164+
rows={generateTableData(data)}
165+
defaultSelectedRows={formattedData(
166+
CollaborativeDetails?.data?.collaboratives[0]?.useCases
167+
)}
168+
onRowSelectionChange={(selected) => {
169+
setSelectedRows(Array.isArray(selected) ? selected : []); // Ensure selected is always an array
170+
}}
171+
/>
172+
</>
173+
) : (
174+
<Loading />
175+
)}
176+
</>
177+
);
178+
};
179+
180+
export default UseCases;

0 commit comments

Comments
 (0)