Skip to content

Commit 48421f6

Browse files
committed
Add a new screen to create image or generate visualization
1 parent 75b3030 commit 48421f6

File tree

1 file changed

+293
-0
lines changed
  • app/[locale]/dashboard/[entityType]/[entitySlug]/charts/components

1 file changed

+293
-0
lines changed
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
import { useEffect, useState } from 'react';
2+
import { useParams } from 'next/navigation';
3+
import { graphql } from '@/gql';
4+
import { ResourceChartImageInput } from '@/gql/generated/graphql';
5+
import { useMutation, useQuery } from '@tanstack/react-query';
6+
import {
7+
Button,
8+
Combobox,
9+
DropZone,
10+
Form,
11+
Select,
12+
Spinner,
13+
Tag,
14+
Text,
15+
toast,
16+
} from 'opub-ui';
17+
18+
import { GraphQL } from '@/lib/api';
19+
import { Icons } from '@/components/icons';
20+
21+
const getAllDatasetsListwithResourcesDoc: any = graphql(`
22+
query getAllDatasets {
23+
datasets {
24+
id
25+
title
26+
slug
27+
resources {
28+
id
29+
name
30+
}
31+
}
32+
}
33+
`);
34+
35+
const createResourceChartImageDoc: any = graphql(`
36+
mutation createResourceChartImage($input: ResourceChartImageInput!) {
37+
createResourceChartImage(input: $input) {
38+
__typename
39+
... on TypeResourceChartImage {
40+
name
41+
id
42+
}
43+
}
44+
}
45+
`);
46+
47+
const ChartsEditor = ({ setEditorView }: { setEditorView: any }) => {
48+
const params = useParams<{ entityType: string; entitySlug: string }>();
49+
50+
const allDatasetsRes: {
51+
data: any;
52+
isLoading: boolean;
53+
refetch: any;
54+
error: any;
55+
isError: boolean;
56+
} = useQuery([`allDatasetsListwithResourcesForCharts`], () =>
57+
GraphQL(
58+
getAllDatasetsListwithResourcesDoc,
59+
{
60+
[params.entityType]: params.entitySlug,
61+
},
62+
[]
63+
)
64+
);
65+
66+
return (
67+
<div>
68+
<div className="flex flex-wrap items-center justify-between gap-3 py-4">
69+
<Text variant="heading2xl">Charts Editor</Text>
70+
<Button
71+
icon={<Icons.cross />}
72+
kind="tertiary"
73+
className="font-color-secondaryOrange"
74+
onClick={() => setEditorView(false)}
75+
>
76+
Close Editor
77+
</Button>
78+
</div>
79+
<div className="py-4">
80+
<Text variant="bodyLg">
81+
Visual displays of information communicate complex data relationships
82+
and data-driven insights in a way that is easy to understand. You can
83+
create a Chart using our in-built chart generator, or Upload an Image.
84+
</Text>
85+
</div>
86+
87+
{allDatasetsRes.isLoading ? (
88+
<div className="flex h-full items-center justify-center">
89+
<Spinner />
90+
</div>
91+
) : (
92+
<div className="flex w-full flex-row gap-4">
93+
<ChartCreate allDatasetsRes={allDatasetsRes} params={params} />
94+
<ChartImageUpload allDatasetsRes={allDatasetsRes} params={params} />
95+
</div>
96+
)}
97+
</div>
98+
);
99+
};
100+
101+
export default ChartsEditor;
102+
103+
const ChartImageUpload = ({
104+
allDatasetsRes,
105+
params,
106+
}: {
107+
allDatasetsRes: any;
108+
params: any;
109+
}) => {
110+
const [files, setFiles] = useState<File | undefined>(undefined);
111+
112+
const [selectedDataset, setSelectedDataset] = useState<any>(null);
113+
114+
const createResourceChartImageMutation: {
115+
mutate: any;
116+
isLoading: boolean;
117+
error: any;
118+
} = useMutation(
119+
[`createResourceChartImage`],
120+
(input: ResourceChartImageInput) =>
121+
GraphQL(
122+
createResourceChartImageDoc,
123+
{
124+
[params.entityType]: params.entitySlug,
125+
},
126+
{ input: input }
127+
),
128+
{
129+
onSuccess: () => {
130+
toast(`Created chart image successfully`);
131+
},
132+
onError: (err: any) => {
133+
toast('Error: ' + err.message.split(':')[0]);
134+
},
135+
}
136+
);
137+
138+
const handleAddImage = () => {
139+
console.log('Add Image :::', selectedDataset, files);
140+
if (selectedDataset && files) {
141+
createResourceChartImageMutation.mutate({
142+
dataset: { set: selectedDataset },
143+
image: files,
144+
});
145+
}
146+
};
147+
148+
return (
149+
<div className="border border-gray-200 flex w-full flex-col justify-between gap-4 rounded-4 bg-basePureWhite p-5 shadow-card">
150+
<div className="flex items-center justify-center gap-3">
151+
<Icons.photo size={48} color="var(--blue-primary-color)" />
152+
<Text variant="headingLg" fontWeight="semibold">
153+
IMAGE
154+
</Text>
155+
</div>
156+
157+
<Form>
158+
<div className="flex flex-col gap-4">
159+
<Combobox
160+
label="Select Dataset"
161+
name="selectDataset"
162+
list={allDatasetsRes?.data?.datasets?.map((item: any) => {
163+
return {
164+
label: item.title,
165+
value: item.id,
166+
};
167+
})}
168+
displaySelected
169+
// selectedValue={selectedDataset}
170+
onChange={(e) => {
171+
setSelectedDataset(e);
172+
}}
173+
required
174+
/>
175+
176+
<DropZone
177+
name={'chartImage'}
178+
label="Select Chart Image"
179+
accept=".png,.jpg,.jpeg,.svg,.tiff"
180+
onDrop={(val) => {
181+
console.log('drop ::', val);
182+
setFiles(val[0]);
183+
}}
184+
outline
185+
allowMultiple={false}
186+
className="bg-greyExtralight"
187+
errorOverlayText={files ? undefined : 'Please select a file'}
188+
required
189+
>
190+
{files ? (
191+
<div className="mt-4 flex items-center justify-between">
192+
<Text variant="bodyMd" color="subdued">
193+
{files.name}
194+
</Text>
195+
<Button
196+
icon={<Icons.delete />}
197+
kind="tertiary"
198+
onClick={() => setFiles(undefined)}
199+
/>
200+
</div>
201+
) : (
202+
<DropZone.FileUpload
203+
actionHint={
204+
<div className="flex flex-col items-center gap-2 p-2">
205+
<Text variant="bodyMd" color="subdued">
206+
Drag and drop
207+
</Text>
208+
<div className="font-color-textDefault w-fit rounded-1 bg-tertiaryAccent px-2 py-1">
209+
Select File
210+
</div>
211+
<Text variant="bodyMd" color="subdued">
212+
*only one image can be added.
213+
</Text>
214+
<Text variant="bodyMd" color="subdued">
215+
Recommended resolution of 16:9 - (1280x720), (1920x1080)
216+
</Text>
217+
<Text variant="bodyMd" color="subdued">
218+
Maximum file size: 100MB
219+
</Text>
220+
<div className="flex flex-row items-center gap-2">
221+
<Text variant="bodyMd" color="subdued">
222+
Supported File Types:
223+
</Text>
224+
<div className="flex flex-row gap-1">
225+
{['PNG', 'JPG', 'SVG', 'TIFF'].map((item, index) => (
226+
<Tag
227+
fillColor="white"
228+
textColor="baseDefault"
229+
key={index}
230+
>
231+
{item}
232+
</Tag>
233+
))}
234+
</div>
235+
</div>
236+
</div>
237+
}
238+
actionTitle={''}
239+
/>
240+
)}
241+
</DropZone>
242+
243+
<div className="flex items-center justify-center">
244+
<Button kind="primary" size="large" onClick={handleAddImage}>
245+
Add Image
246+
</Button>
247+
</div>
248+
</div>
249+
</Form>
250+
</div>
251+
);
252+
};
253+
254+
const ChartCreate = ({
255+
allDatasetsRes,
256+
params,
257+
}: {
258+
allDatasetsRes: any;
259+
params: any;
260+
}) => {
261+
return (
262+
<div className="border border-gray-200 flex w-full flex-col justify-between rounded-4 bg-basePureWhite p-5 shadow-card">
263+
<div className="flex items-center justify-center gap-3">
264+
<Icons.chart size={48} color="var(--blue-primary-color)" />
265+
<Text variant="headingLg" fontWeight="semibold">
266+
CHART
267+
</Text>
268+
</div>
269+
270+
<Form>
271+
<div className="flex flex-col gap-4">
272+
<Select
273+
disabled
274+
name={'chartCreateSelectDataset'}
275+
label="Select Dataset"
276+
options={allDatasetsRes?.data?.datasets?.map((item: any) => {
277+
return {
278+
label: item.title,
279+
value: item.id,
280+
};
281+
})}
282+
/>
283+
284+
<div className="flex items-center justify-center">
285+
<Button kind="primary" size="large">
286+
Create Chart
287+
</Button>
288+
</div>
289+
</div>
290+
</Form>
291+
</div>
292+
);
293+
};

0 commit comments

Comments
 (0)