Skip to content

Commit

Permalink
feat: year in review reports
Browse files Browse the repository at this point in the history
  • Loading branch information
bohdangarchu committed Dec 19, 2024
1 parent d25365b commit c8f62b6
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 16 deletions.
13 changes: 12 additions & 1 deletion src/app/download-portal/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import AccordionContainer from '@/components/Accordions/AccordionContainer';
import DownloadCountryAccordion from '@/components/DownloadCountryAccordions/DownloadCountryAccordions';
import CountryReports from '@/components/DownloadPortal/CountryReports';
import YearInReviewReports from '@/components/DownloadPortal/YearInReviewReports';
import container from '@/container';
import { TITLE } from '@/domain/entities/download/Country';
import { GlobalDataRepository } from '@/domain/repositories/GlobalDataRepository';
Expand All @@ -9,7 +10,12 @@ export default async function DownloadPortal() {
const globalRepo = container.resolve<GlobalDataRepository>('GlobalDataRepository');
const countryMapDataPromise = globalRepo.getMapDataForCountries();
const countryCodesPromise = globalRepo.getCountryCodes();
const [countryCodesData, countryMapData] = await Promise.all([countryCodesPromise, countryMapDataPromise]);
const yearInReviewsPromise = globalRepo.getYearInReviews();
const [countryCodesData, countryMapData, yearInReviews] = await Promise.all([
countryCodesPromise,
countryMapDataPromise,
yearInReviewsPromise,
]);

const countries =
countryMapData?.features.map((feature) => ({
Expand All @@ -24,7 +30,12 @@ export default async function DownloadPortal() {
<h1>Download Portal</h1>
<div>
<AccordionContainer
multipleSelectionMode
items={[
{
title: 'WFP Real Time Monitoring: Year in Review Reports',
content: <YearInReviewReports yearInReviewReports={yearInReviews} />,
},
{
title: 'Country Reports',
content: <CountryReports countryCodesData={countryCodesData} />,
Expand Down
12 changes: 7 additions & 5 deletions src/components/DownloadPortal/CountryReports.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import PdfPreview from '@/components/Pdf/PdfPreview';
import SearchBar from '@/components/Search/SearchBar';
import CustomTable from '@/components/Table/CustomTable';
import { useChatbot } from '@/domain/contexts/ChatbotContext';
import { useSnackbar } from '@/domain/contexts/SnackbarContext';
import { CountryCodesData } from '@/domain/entities/country/CountryCodesData';
import CountryReportsProps from '@/domain/props/CountryReportsProps';
import { PdfFile } from '@/domain/props/PdfViewerProps';
Expand All @@ -18,8 +19,8 @@ export default function CountryReports({ countryCodesData }: CountryReportsProps
const [error, setError] = useState<string | null>(null);
const [selectedCountry, setSelectedCountry] = useState<CountryCodesData | null>(null);

const chatBot = useChatbot();
const { initiateChatAboutReport } = chatBot;
const { initiateChatAboutReport } = useChatbot();
const { showSnackBar } = useSnackbar();

const toggleModal = () => setModalOpen((prev) => !prev);

Expand All @@ -34,13 +35,14 @@ export default function CountryReports({ countryCodesData }: CountryReportsProps
</div>
<CustomTable
columns={DownloadPortalOperations.getColumns()}
data={DownloadPortalOperations.formatTableData(
data={DownloadPortalOperations.formatCountryTableData(
filteredData,
setSelectedCountry,
initiateChatAboutReport,
setPdfFile,
setError,
toggleModal
toggleModal,
showSnackBar
)}
ariaLabel="Country Reports"
/>
Expand All @@ -51,7 +53,7 @@ export default function CountryReports({ countryCodesData }: CountryReportsProps
error={error}
onDownloadPdf={() => {
if (selectedCountry) {
DownloadPortalOperations.downloadPdf(selectedCountry);
DownloadPortalOperations.downloadCountryReport(selectedCountry, showSnackBar);
}
}}
/>
Expand Down
52 changes: 52 additions & 0 deletions src/components/DownloadPortal/YearInReviewReports.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'use client';

import { useState } from 'react';

import { useChatbot } from '@/domain/contexts/ChatbotContext';
import { useSnackbar } from '@/domain/contexts/SnackbarContext';
import { YearInReview } from '@/domain/entities/YearInReview';
import { PdfFile } from '@/domain/props/PdfViewerProps';
import YearInReviewReportsProps from '@/domain/props/YearInReviewReportsProps';
import { DownloadPortalOperations } from '@/operations/download-portal/DownloadPortalOperations';

import PdfPreview from '../Pdf/PdfPreview';
import CustomTable from '../Table/CustomTable';

export default function YearInReviewReports({ yearInReviewReports }: YearInReviewReportsProps) {
const [isModalOpen, setModalOpen] = useState(false);
const [pdfFile, setPdfFile] = useState<PdfFile | null>(null);
const [error, setError] = useState<string | null>(null);
const [selectedReport, setSelectedReport] = useState<YearInReview | null>(null);
const { initiateChatAboutReport } = useChatbot();
const toggleModal = () => setModalOpen((prev) => !prev);
const { showSnackBar } = useSnackbar();

return (
<div>
<CustomTable
columns={DownloadPortalOperations.getColumns()}
data={DownloadPortalOperations.formatYearInReviewTableData(
yearInReviewReports,
setSelectedReport,
initiateChatAboutReport,
setPdfFile,
setError,
toggleModal,
showSnackBar
)}
ariaLabel="Year In Review Reports"
/>
<PdfPreview
isModalOpen={isModalOpen}
toggleModal={toggleModal}
pdfFile={pdfFile}
error={error}
onDownloadPdf={() => {
if (selectedReport) {
DownloadPortalOperations.downloadYearInReview(selectedReport, showSnackBar);
}
}}
/>
</div>
);
}
5 changes: 5 additions & 0 deletions src/domain/props/YearInReviewReportsProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { YearInReview } from '../entities/YearInReview';

export default interface YearInReviewReportsProps {
yearInReviewReports: YearInReview[];
}
110 changes: 100 additions & 10 deletions src/operations/download-portal/DownloadPortalOperations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { Bot } from 'lucide-react';

import { CountryCodesData } from '@/domain/entities/country/CountryCodesData';
import { ICountryData } from '@/domain/entities/download/Country';
import { SNACKBAR_SHORT_DURATION } from '@/domain/entities/snackbar/Snackbar';
import { YearInReview } from '@/domain/entities/YearInReview';
import { SnackbarPosition, SnackbarStatus } from '@/domain/enums/Snackbar';
import { CustomTableColumns } from '@/domain/props/CustomTableProps';
import { SnackbarProps } from '@/domain/props/SnackbarProps';

export class DownloadPortalOperations {
static getColumns(): CustomTableColumns {
Expand All @@ -16,13 +20,14 @@ export class DownloadPortalOperations {
] as CustomTableColumns;
}

static formatTableData(
static formatCountryTableData(
data: CountryCodesData[],
setSelectedCountry: (countryData: CountryCodesData) => void,
initiateChatAboutReport: (country: string, report: string) => Promise<void>,
setPdfFile: (file: Blob | null) => void,
setError: (error: string | null) => void,
toggleModal: () => void
toggleModal: () => void,
showSnackBar: (snackbarProps: SnackbarProps) => void
) {
return data.map((item) => ({
keyColumn: item.country.name,
Expand All @@ -41,7 +46,7 @@ export class DownloadPortalOperations {
<div className="flex justify-center items-center">
<DocumentDownload
size={20}
onClick={() => DownloadPortalOperations.downloadPdf(item)}
onClick={() => DownloadPortalOperations.downloadCountryReport(item, showSnackBar)}
className="cursor-pointer"
/>
</div>
Expand All @@ -58,6 +63,53 @@ export class DownloadPortalOperations {
}));
}

static formatYearInReviewTableData(
data: YearInReview[],
setSelectedReport: (report: YearInReview) => void,
initiateChatAboutReport: (country: string, report: string) => Promise<void>,
setPdfFile: (file: Blob | null) => void,
setError: (error: string | null) => void,
toggleModal: () => void,
showSnackBar: (snackbarProps: SnackbarProps) => void
) {
return data.map((item) => ({
keyColumn: item.label,
preview: (
<div className="flex justify-center items-center">
<SearchNormal1
size={20}
onClick={() => {
setSelectedReport(item);
DownloadPortalOperations.handlePreview(item.url, setPdfFile, setError);
toggleModal();
}}
className="cursor-pointer"
/>
</div>
),
download: (
<div className="flex justify-center items-center">
<DocumentDownload
size={20}
onClick={() => DownloadPortalOperations.downloadYearInReview(item, showSnackBar)}
className="cursor-pointer"
/>
</div>
),
chat: (
<div className="flex justify-center items-center">
<Bot
size={20}
onClick={() => {
initiateChatAboutReport(item.label, item.url);
}}
className="cursor-pointer"
/>
</div>
),
}));
}

static downloadJsonFile(data: ICountryData[], country: string): void {
const a = document.createElement('a');
const file = new Blob([JSON.stringify(data)], { type: 'application/json' });
Expand All @@ -77,13 +129,51 @@ export class DownloadPortalOperations {
return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
}

static downloadPdf(country: CountryCodesData) {
const link = document.createElement('a');
link.href = country.url.summary;
link.download = `${country.country.name}.pdf`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
static async downloadCountryReport(
country: CountryCodesData,
showSnackBar: (snackbarProps: SnackbarProps) => void
): Promise<void> {
await this.downloadFile(country.url.summary, `${country.country.name}.pdf`, showSnackBar);
}

static async downloadYearInReview(
yearInReview: YearInReview,
showSnackBar: (snackbarProps: SnackbarProps) => void
): Promise<void> {
await this.downloadFile(yearInReview.url, `${yearInReview.label}.pdf`, showSnackBar);
}

private static async downloadFile(
fileUrl: string,
fileName: string,
showSnackBar?: (snackbarProps: SnackbarProps) => void
): Promise<void> {
try {
const response = await fetch(fileUrl);
if (!response.ok) throw new Error('Failed to download file');

const blob = await response.blob();
const url = window.URL.createObjectURL(blob);

const link = document.createElement('a');
link.href = url;
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

// Cleanup URL object
window.URL.revokeObjectURL(url);
} catch {
if (showSnackBar) {
showSnackBar({
message: 'Error downloading file',
status: SnackbarStatus.Error,
position: SnackbarPosition.BottomRight,
duration: SNACKBAR_SHORT_DURATION,
});
}
}
}

static async fetchPdfAsByteStream(url: string): Promise<ArrayBuffer> {
Expand Down

0 comments on commit c8f62b6

Please sign in to comment.