Skip to content

Commit

Permalink
Merge pull request #72 from helsingborg-stad/feature/export-excel
Browse files Browse the repository at this point in the history
Feature/export-excel
  • Loading branch information
D3nnis38 authored Mar 12, 2024
2 parents 56565b4 + 653f72e commit 999a135
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 61 deletions.
6 changes: 6 additions & 0 deletions src/api/event/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,9 @@ import { Event } from 'types/event';
import { client } from '../baseAxios';

export const getEvents = (filter?: string) => client.get<Event[]>(`/zones/events${filter !== '' ? `?${filter}` : ''}`);
export const exportEvents = (filter?: string) => client.get<Blob>(
`/zones/events/export${filter !== '' ? `?${filter}` : ''}`,
{
responseType: 'blob',
},
);
4 changes: 3 additions & 1 deletion src/hooks/useEventApi.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { getEvents } from 'api/event';
import { getEvents, exportEvents } from 'api/event';

export const useEventApi = () => {
const getAllEvents = (filter?: string) => getEvents(filter);
const exportAllEvents = (filter?: string) => exportEvents(filter);

return {
getAllEvents,
exportAllEvents,
};
};
7 changes: 4 additions & 3 deletions src/modules/Delivery/components/DeliveryList/DeliveryList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import * as Styled from './styled';

export const DeliveryList = () => {
const {
fetchEvents, events, error, isLoading,
fetchEvents, exportEvents, events, error, isLoading,
} = useGetEvents();
const {
filters, checkFilter, resetFilters, triggerReload, filterOptions,
activeFilters,
activeFilters, exportEventsToExcel,
setDateTimeFilter,
} = useGetEventFilters({ fetchEvents });
} = useGetEventFilters({ fetchEvents, exportEvents });

if (isLoading) {
return (
Expand Down Expand Up @@ -46,6 +46,7 @@ export const DeliveryList = () => {
triggerReload={triggerReload}
filterOptions={filterOptions}
setDateTimeFilter={setDateTimeFilter}
exportEventsToExcel={exportEventsToExcel}
/>
<ListHeader />
<ListContent events={events} resetFilters={resetFilters} />
Expand Down
119 changes: 65 additions & 54 deletions src/modules/Delivery/components/DeliveryList/FilterList/FilterList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ type FilterListProps = {
resetFilters: (filter?: FilterOptions) => void;
triggerReload: () => void;
activeFilters: ActiveFilterType;
setDateTimeFilter: (filterName: string) => (data: DateTimeFilterSelected) => void
setDateTimeFilter: (filterName: string) => (data: DateTimeFilterSelected) => void;
exportEventsToExcel: (filter?: string) => void;
};

export const FilterList: FC<FilterListProps> = ({
filters, checkFilter, resetFilters, triggerReload,
filterOptions,
activeFilters, setDateTimeFilter,
exportEventsToExcel,
}) => {
if (!filters || !filterOptions) {
return null;
Expand All @@ -37,59 +39,60 @@ export const FilterList: FC<FilterListProps> = ({

return (
<Styled.Container>
<FilterButtonDate
activeFilters={activeFilters.dates}
label="Datum"
filterOptions={filterOptions.dates}
selected={filters.dates}
onClick={setDateTimeFilter('dates')}
/>
<WeekdayFilter
filterOptions={filterOptions.weekdays}
weekdayFilter={filters.weekdays}
checkFilter={checkFilter}
resetFilters={resetFilters}
triggerReload={triggerReload}
activeFilters={activeFilters.weekdays}
/>
<FilterButtonDate
activeFilters={activeFilters.timeInterval}
label="Tid"
filterOptions={filterOptions.timeInterval}
selected={filters.timeInterval}
onClick={setDateTimeFilter('timeInterval')}
/>
<NameFilter
nameFilter={filters.names}
checkFilter={checkFilter}
resetFilters={resetFilters}
triggerReload={triggerReload}
activeFilters={activeFilters.names}
/>
<AreaFilter
areaFilter={filters.areas}
checkFilter={checkFilter}
resetFilters={resetFilters}
triggerReload={triggerReload}
activeFilters={activeFilters.areas}
/>
<DistributorFilter
distributorFilter={filters.distributors}
filterOptions={filterOptions.distributors}
checkFilter={checkFilter}
resetFilters={resetFilters}
triggerReload={triggerReload}
activeFilters={activeFilters.distributors}
/>
<OrganisationFilter
organisationFilter={filters.organisations}
filterOptions={filterOptions.organisations}
checkFilter={checkFilter}
resetFilters={resetFilters}
triggerReload={triggerReload}
activeFilters={activeFilters.organisations}
/>
{
<Styled.FilterContainer>
<FilterButtonDate
activeFilters={activeFilters.dates}
label="Datum"
filterOptions={filterOptions.dates}
selected={filters.dates}
onClick={setDateTimeFilter('dates')}
/>
<WeekdayFilter
filterOptions={filterOptions.weekdays}
weekdayFilter={filters.weekdays}
checkFilter={checkFilter}
resetFilters={resetFilters}
triggerReload={triggerReload}
activeFilters={activeFilters.weekdays}
/>
<FilterButtonDate
activeFilters={activeFilters.timeInterval}
label="Tid"
filterOptions={filterOptions.timeInterval}
selected={filters.timeInterval}
onClick={setDateTimeFilter('timeInterval')}
/>
<NameFilter
nameFilter={filters.names}
checkFilter={checkFilter}
resetFilters={resetFilters}
triggerReload={triggerReload}
activeFilters={activeFilters.names}
/>
<AreaFilter
areaFilter={filters.areas}
checkFilter={checkFilter}
resetFilters={resetFilters}
triggerReload={triggerReload}
activeFilters={activeFilters.areas}
/>
<DistributorFilter
distributorFilter={filters.distributors}
filterOptions={filterOptions.distributors}
checkFilter={checkFilter}
resetFilters={resetFilters}
triggerReload={triggerReload}
activeFilters={activeFilters.distributors}
/>
<OrganisationFilter
organisationFilter={filters.organisations}
filterOptions={filterOptions.organisations}
checkFilter={checkFilter}
resetFilters={resetFilters}
triggerReload={triggerReload}
activeFilters={activeFilters.organisations}
/>
{
hasActiveFilter && (
<Button
type="button"
Expand All @@ -101,6 +104,14 @@ export const FilterList: FC<FilterListProps> = ({
)
}

</Styled.FilterContainer>
<Button
onClick={() => exportEventsToExcel()}
type="button"
buttonSize={ButtonSize.SMALL}
>
Exportera till excel
</Button>
</Styled.Container>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import styled from 'styled-components';

export const Container = styled.div`
export const FilterContainer = styled.div`
display: flex;
gap: 6px;
`;

export const Container = styled.div`
display: flex;
justify-content: space-between;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import { useGetFilterValues } from '../useGetFilterValues';

type HookProps = {
fetchEvents: (filter?: string) => void;
exportEvents: (filter?: string) => void;
};

export const useGetEventFilters = ({ fetchEvents }: HookProps) => {
export const useGetEventFilters = ({ fetchEvents, exportEvents }: HookProps) => {
const { allWeekdays, dates, timeInterval } = useGetFilterValues();
const { getFiltersForEvent } = useFilterApi();
const [filterOptions, setFilterOptions] = useState<FilterOptionType>();
const [filters, setFilters] = useState<FilterType>();
const [filterState, setFilterState] = useState<string>();
const [reload, setReload] = useState(true);
const [activeFilters, setActiveFilters] = useState<ActiveFilterType>({
organisations: 0,
Expand Down Expand Up @@ -200,6 +202,7 @@ export const useGetEventFilters = ({ fetchEvents }: HookProps) => {
});

const filter = params.toString();
setFilterState(filter);

// Sets URL to current filter(s) & fetches filtered data
window.history.replaceState({}, '', `${window.location.pathname}${filter !== '' ? `?${filter}` : ''}`);
Expand All @@ -208,6 +211,8 @@ export const useGetEventFilters = ({ fetchEvents }: HookProps) => {
}
}, [filters, reload]);

const exportEventsToExcel = () => exportEvents(filterState);

return {
filterOptions,
activeFilters,
Expand All @@ -216,5 +221,6 @@ export const useGetEventFilters = ({ fetchEvents }: HookProps) => {
resetFilters,
triggerReload,
setDateTimeFilter,
exportEventsToExcel,
};
};
18 changes: 17 additions & 1 deletion src/modules/Delivery/hooks/useGetEvents/useGetEvents.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useState } from 'react';
import { Event } from 'types/event';
import { useEventApi } from 'hooks/useEventApi';
import { downloadBlobAsFile } from 'utils/downloadFile';

export const useGetEvents = () => {
const { getAllEvents } = useEventApi();
const { getAllEvents, exportAllEvents } = useEventApi();
const [events, setEvents] = useState<Event[]>();
const [error, setError] = useState<boolean>(false);
const [isLoading, setIsLoading] = useState<boolean>(false);
Expand All @@ -20,9 +21,24 @@ export const useGetEvents = () => {
setIsLoading(false);
};

const exportEvents = async (filter?: string) => {
try {
setError(false);
setIsLoading(true);
const { data } = await exportAllEvents(filter);
const blob = new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
downloadBlobAsFile(blob, 'events.xlsx');
} catch (e) {
setError(true);
} finally {
setIsLoading(false);
}
};

return {
events,
fetchEvents,
exportEvents,
error,
isLoading,
};
Expand Down
8 changes: 8 additions & 0 deletions src/utils/downloadFile/downloadBlobAsFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const downloadBlobAsFile = (blob: Blob, filename: string): void => {
const objectUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = objectUrl;
link.setAttribute('download', filename);
link.click();
setTimeout(() => window.URL.revokeObjectURL(objectUrl), 0);
};
1 change: 1 addition & 0 deletions src/utils/downloadFile/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './downloadBlobAsFile';
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './useDateConverter';
export * from './downloadFile';

0 comments on commit 999a135

Please sign in to comment.