Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src/components/BodyWeight/WeightFilter/WeightFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { useState } from 'react';
import { Button, ButtonGroup, Box } from '@mui/material';

interface WeightFilterProps {
onFilter: (filter: string) => void;
}

const WeightFilter: React.FC<WeightFilterProps> = ({ onFilter }) => {
const [activeFilter, setActiveFilter] = useState('all');

const handleFilterClick = (filter: string) => {
setActiveFilter(filter);
onFilter(filter);
};

return (
<Box sx={{ display: 'flex', justifyContent: 'center', my: 2 }}>
<ButtonGroup variant="outlined" aria-label="outlined primary button group">
<Button
variant={activeFilter === 'all' ? 'contained' : 'outlined'}
onClick={() => handleFilterClick('all')}
>
All
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you mark the texts as translatable? you just need to add a key to public/locales/en/translation.json and then you can use it with t('')

</Button>
<Button
variant={activeFilter === 'year' ? 'contained' : 'outlined'}
onClick={() => handleFilterClick('year')}
>
Last Year
</Button>
<Button
variant={activeFilter === 'sixMonths' ? 'contained' : 'outlined'}
onClick={() => handleFilterClick('sixMonths')}
>
Last Six Months
</Button>
<Button
variant={activeFilter === 'month' ? 'contained' : 'outlined'}
onClick={() => handleFilterClick('month')}
>
Last Month
</Button>
</ButtonGroup>
</Box>
);
};

export default WeightFilter;
3 changes: 3 additions & 0 deletions src/components/BodyWeight/WeightFilter/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import WeightFilter from './WeightFilter';

export default WeightFilter;
92 changes: 67 additions & 25 deletions src/components/BodyWeight/index.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,70 @@
import { Box, Stack } from "@mui/material";
import { useBodyWeightQuery } from "components/BodyWeight/queries";
import { WeightTable } from "components/BodyWeight/Table";
import { WeightChart } from "components/BodyWeight/WeightChart";
import { AddBodyWeightEntryFab } from "components/BodyWeight/widgets/fab";
import { LoadingPlaceholder } from "components/Core/LoadingWidget/LoadingWidget";
import { WgerContainerRightSidebar } from "components/Core/Widgets/Container";
import { OverviewEmpty } from "components/Core/Widgets/OverviewEmpty";
import { useTranslation } from "react-i18next";
import React, { useState, useEffect } from 'react';
import { Box, Stack } from '@mui/material';
import { useBodyWeightQuery } from 'components/BodyWeight/queries';
import { WeightTable } from 'components/BodyWeight/Table';
import { WeightChart } from 'components/BodyWeight/WeightChart';
import WeightFilter from 'components/BodyWeight/WeightFilter';
import { AddBodyWeightEntryFab } from 'components/BodyWeight/widgets/fab';
import { LoadingPlaceholder } from 'components/Core/LoadingWidget/LoadingWidget';
import { WgerContainerRightSidebar } from 'components/Core/Widgets/Container';
import { OverviewEmpty } from 'components/Core/Widgets/OverviewEmpty';
import { useTranslation } from 'react-i18next';
import { WeightEntry } from 'components/BodyWeight/model';

export const BodyWeight = () => {
const [t] = useTranslation();
const weightyQuery = useBodyWeightQuery();
const [t] = useTranslation();
const weightyQuery = useBodyWeightQuery();
const [filteredData, setFilteredData] = useState<WeightEntry[]>([]);

return weightyQuery.isLoading
? <LoadingPlaceholder />
: <WgerContainerRightSidebar
title={t("weight")}
mainContent={<Stack spacing={2}>
{weightyQuery.data!.length === 0 && <OverviewEmpty />}
<WeightChart weights={weightyQuery.data!} />
<Box sx={{ mt: 4 }} />
<WeightTable weights={weightyQuery.data!} />
</Stack>
}
fab={<AddBodyWeightEntryFab />}
/>;
};
useEffect(() => {
if (weightyQuery.data) {
setFilteredData(weightyQuery.data);
}
}, [weightyQuery.data]);

const handleFilter = (filter: string) => {
const now = new Date();
let filteredWeights: WeightEntry[] = [];
if (weightyQuery.data) {
switch (filter) {
case 'year':
filteredWeights = weightyQuery.data.filter((entry) =>
new Date(entry.date) >= new Date(now.setFullYear(now.getFullYear() - 1))
);
break;
case 'sixMonths':
filteredWeights = weightyQuery.data.filter((entry) =>
new Date(entry.date) >= new Date(now.setMonth(now.getMonth() - 6))
);
break;
case 'month':
filteredWeights = weightyQuery.data.filter((entry) =>
new Date(entry.date) >= new Date(now.setMonth(now.getMonth() - 1))
);
break;
case 'all':
default:
filteredWeights = weightyQuery.data;
}
setFilteredData(filteredWeights);
}
};

return weightyQuery.isLoading ? (
<LoadingPlaceholder />
) : (
<WgerContainerRightSidebar
title={t('weight')}
mainContent={
<Stack spacing={2}>
<WeightFilter onFilter={handleFilter} />
{filteredData.length === 0 && <OverviewEmpty />}
<WeightChart weights={filteredData} />
<Box sx={{ mt: 4 }} />
<WeightTable weights={filteredData} />
</Stack>
}
fab={<AddBodyWeightEntryFab />}
/>
);
};
141 changes: 90 additions & 51 deletions src/components/Dashboard/WeightCard.tsx
Original file line number Diff line number Diff line change
@@ -1,70 +1,109 @@
import AddIcon from "@mui/icons-material/Add";
import { Box, Button, Card, CardActions, CardContent, CardHeader, IconButton, } from '@mui/material';
import React, { useState, useEffect } from 'react';
import { Box, Button, Card, CardActions, CardContent, CardHeader, IconButton } from '@mui/material';
import Tooltip from "@mui/material/Tooltip";
import AddIcon from "@mui/icons-material/Add";
import { WeightForm } from "components/BodyWeight/Form/WeightForm";
import { WeightEntry } from "components/BodyWeight/model";
import { useBodyWeightQuery } from "components/BodyWeight/queries";
import { WeightTableDashboard } from "components/BodyWeight/TableDashboard/TableDashboard";
import { WeightChart } from "components/BodyWeight/WeightChart";
import { LoadingPlaceholder } from "components/Core/LoadingWidget/LoadingWidget";
import { WgerModal } from "components/Core/Modals/WgerModal";
import { EmptyCard } from "components/Dashboard/EmptyCard";
import React from 'react';
import { useTranslation } from "react-i18next";
import { makeLink, WgerLink } from "utils/url";
import WeightFilter from 'components/BodyWeight/WeightFilter';
import { useBodyWeightQuery } from 'components/BodyWeight/queries';
import { LoadingPlaceholder } from 'components/Core/LoadingWidget/LoadingWidget';
import { EmptyCard } from 'components/Dashboard/EmptyCard';

export const WeightCard = () => {

const [t] = useTranslation();
const weightyQuery = useBodyWeightQuery();

return (<>{weightyQuery.isLoading
? <LoadingPlaceholder />
: <>{weightyQuery.data?.length !== undefined && weightyQuery.data?.length > 0
? <WeightCardContent entries={weightyQuery.data} />
: <EmptyCard
title={t('weight')}
modalContent={<WeightForm />}
/>}</>
}
</>);
return (
<>
{weightyQuery.isLoading
? <LoadingPlaceholder />
: <>
{weightyQuery.data?.length !== undefined && weightyQuery.data?.length > 0
? <WeightCardContent entries={weightyQuery.data} />
: <EmptyCard
title={t('weight')}
modalContent={<WeightForm />}
/>}
</>
}
</>
);
};
export const WeightCardContent = (props: { entries: WeightEntry[] }) => {

const [openModal, setOpenModal] = React.useState(false);
export const WeightCardContent = (props: { entries: WeightEntry[] }) => {
const [openModal, setOpenModal] = useState(false);
const handleOpenModal = () => setOpenModal(true);
const handleCloseModal = () => setOpenModal(false);
const [t, i18n] = useTranslation();
const [filteredData, setFilteredData] = useState<WeightEntry[]>(props.entries);

useEffect(() => {
setFilteredData(props.entries);
}, [props.entries]);

return (<>
<Card>
<CardHeader
title={t('weight')}
subheader={'.'}
/>
<CardContent sx={{ height: '500px', overflow: 'auto' }}>
<WeightChart weights={props.entries} height={200} />
<Box sx={{ mt: 2, }}>
<WeightTableDashboard weights={props.entries} />
</Box>
</CardContent>
<CardActions sx={{
justifyContent: "space-between",
alignItems: "flex-start",
}}>
<Button size="small"
href={makeLink(WgerLink.WEIGHT_OVERVIEW, i18n.language)}>
{t('seeDetails')}
</Button>
<Tooltip title={t('addEntry')}>
<IconButton onClick={handleOpenModal}>
<AddIcon />
</IconButton>
</Tooltip>
</CardActions>
</Card>
<WgerModal title={t('add')} isOpen={openModal} closeFn={handleCloseModal}>
<WeightForm closeFn={handleCloseModal} />
</WgerModal>
</>);
};
const handleFilter = (filter: string) => {
const now = new Date();
let filteredWeights: WeightEntry[] = [];
switch (filter) {
case 'year':
filteredWeights = props.entries.filter((entry) =>
new Date(entry.date) >= new Date(now.setFullYear(now.getFullYear() - 1))
);
break;
case 'sixMonths':
filteredWeights = props.entries.filter((entry) =>
new Date(entry.date) >= new Date(now.setMonth(now.getMonth() - 6))
);
break;
case 'month':
filteredWeights = props.entries.filter((entry) =>
new Date(entry.date) >= new Date(now.setMonth(now.getMonth() - 1))
);
break;
case 'all':
default:
filteredWeights = props.entries;
}
setFilteredData(filteredWeights);
};

return (
<>
<Card>
<CardHeader
title={t('weight')}
subheader={'.'}
/>
<CardContent sx={{ height: '500px', overflow: 'auto' }}>
<WeightFilter onFilter={handleFilter} />
<WeightChart weights={filteredData} height={200} />
<Box sx={{ mt: 2 }}>
<WeightTableDashboard weights={filteredData} />
</Box>
</CardContent>
<CardActions sx={{
justifyContent: "space-between",
alignItems: "flex-start",
}}>
<Button size="small"
href={makeLink(WgerLink.WEIGHT_OVERVIEW, i18n.language)}>
{t('seeDetails')}
</Button>
<Tooltip title={t('addEntry')}>
<IconButton onClick={handleOpenModal}>
<AddIcon />
</IconButton>
</Tooltip>
</CardActions>
</Card>
<WgerModal title={t('add')} isOpen={openModal} closeFn={handleCloseModal}>
<WeightForm closeFn={handleCloseModal} />
</WgerModal>
</>
);
};
Loading