Skip to content

Commit

Permalink
added filters for kitchen outcomes
Browse files Browse the repository at this point in the history
  • Loading branch information
charlesjin123 committed Jan 8, 2025
1 parent cbd80e9 commit f5fc00c
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 22 deletions.
85 changes: 79 additions & 6 deletions client/src/Visualizations/KitchenOutcomeViz.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,45 @@ function KitchenOutcomesVisualization() {
const [orgName, setOrgName] = useState<string | undefined>('');
const [orgId, setOrgId] = useState('');
const [year, setYear] = useState<number | ''>('');
const [mealType, setMealType] = useState<string>('All');
const [mealRange, setMealRange] = useState<string>('All');

const tabNames = [
'Hunger Relief',
'Social Enterprise',
'Capital Projects',
'Organization Info',
];

const mealTypes = [
'All',
'Childcare Meals',
'School Meals',
'Soup Kitchen (onsite)',
'Shelter Meals (offsite)',
'Meals for Supportive/Transitional Housing',
'Meals For Seniors',
'Medically Tailored Meals',
];

const mealRanges = [
'All',
'0-100000',
'100000-500000',
'500000-1000000',
'1000000+',
];

const handleMealTypeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setMealType(event.target.value);
};

const handleMealRangeChange = (
event: React.ChangeEvent<HTMLInputElement>,
) => {
setMealRange(event.target.value);
};

useEffect(() => {
const fetchOrgList = async () => {
try {
Expand Down Expand Up @@ -730,7 +762,11 @@ function KitchenOutcomesVisualization() {
},
};

const fetchAllNetworkAverages = async (selectedYear: number) => {
const fetchAllNetworkAverages = async (
selectedYear: number,
mealTypeFilter: string,
mealRangeFilter: string,
) => {
console.log('Fetching network averages for year:', selectedYear);

const fields = [
Expand All @@ -754,10 +790,10 @@ function KitchenOutcomesVisualization() {
fields.map(async (field) => {
try {
console.log(
`trying to get network avg route with ${field} ${selectedYear}`,
`trying to get network avg route with ${field} ${selectedYear} ${mealTypeFilter} ${mealRangeFilter}`,
);
const response = await getData(
`kitchen_outcomes/network-average/${field}/${selectedYear}`,
`kitchen_outcomes/network-average/${field}/${selectedYear}/${mealTypeFilter}/${mealRangeFilter}`,
);
averages[field] = response.data.average;
} catch (error) {
Expand All @@ -770,7 +806,7 @@ function KitchenOutcomesVisualization() {
try {
console.log('trying to call route with year: ', selectedYear);
const response2 = await getData(
`kitchen_outcomes/distri/${selectedYear}`,
`kitchen_outcomes/distri/${selectedYear}/${mealTypeFilter}/${mealRangeFilter}`,
);
console.log('response data: ', response2.data);
const ageRaceData = response2.data;
Expand All @@ -789,9 +825,9 @@ function KitchenOutcomesVisualization() {

useEffect(() => {
if (year) {
fetchAllNetworkAverages(Number(year));
fetchAllNetworkAverages(Number(year), mealType, mealRange);
}
}, [year]);
}, [year, mealType, mealRange]);

return (
<Container maxWidth="lg">
Expand Down Expand Up @@ -846,6 +882,43 @@ function KitchenOutcomesVisualization() {
))}
</TextField>
</Grid>
<Grid item xs={12}>
<Typography variant="subtitle1" sx={{ mb: 1 }}>
Network Average Filters
</Typography>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<TextField
select
size="small"
fullWidth
label="Meal Type"
value={mealType}
onChange={handleMealTypeChange}
>
{mealTypes.map((type) => (
<MenuItem key={type} value={type}>
{type}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<TextField
select
size="small"
fullWidth
label="Number of Meals Served"
value={mealRange}
onChange={handleMealRangeChange}
>
{mealRanges.map((range) => (
<MenuItem key={range} value={range}>
{range}
</MenuItem>
))}
</TextField>
</Grid>
</Grid>

{/* Tabs - now left justified */}
Expand Down
21 changes: 15 additions & 6 deletions server/src/controllers/kitchen.outcomes.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const distriController = async (
res: express.Response,
next: express.NextFunction,
) => {
const { year } = req.params;
const { year, mealType, mealRange } = req.params;

if (!year) {
next(ApiError.missingFields(['year']));
Expand All @@ -39,7 +39,11 @@ const distriController = async (
year,
);

const ageDistribution = await calculateAgeAndRaceDistributions(yearNum);
const ageDistribution = await calculateAgeAndRaceDistributions(
yearNum,
mealType,
mealRange,
);

res.status(StatusCode.OK).json({
year: yearNum,
Expand All @@ -61,10 +65,10 @@ const getNetworkAverageController = async (
res: express.Response,
next: express.NextFunction,
) => {
const { field, year } = req.params;
const { field, year, mealType, mealRange } = req.params;

if (!field || !year) {
next(ApiError.missingFields(['field', 'year']));
if (!field || !year || !mealType || !mealRange) {
next(ApiError.missingFields(['field', 'year', 'mealType', 'mealRange']));
return;
}

Expand All @@ -75,7 +79,12 @@ const getNetworkAverageController = async (
return;
}

const average = await getNetworkAverage(field, yearNum);
const average = await getNetworkAverage(
field,
yearNum,
mealType,
mealRange,
);

res.status(StatusCode.OK).json({
field,
Expand Down
9 changes: 6 additions & 3 deletions server/src/routes/kitchen.outcomes.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ import {

const router = express.Router();

router.get('/distri/:year', isAuthenticated, distriController);

router.get(
'/distri/:year/:mealType/:mealRange',
isAuthenticated,
distriController,
);

// router.get('/:year/:orgName', isAuthenticated, getOneKitchenOutcomesController);
router.get('/:year/:orgId', isAuthenticated, getOneKitchenOutcomesController); // no authentication for now
Expand All @@ -40,7 +43,7 @@ router.delete('/delete/:id', isAdmin, deleteKitchenOutcomeByIdController);
router.post('/add/', isAuthenticated, addKitchenOutcomesController);

router.get(
'/network-average/:field/:year',
'/network-average/:field/:year/:mealType/:mealRange',
isAuthenticated,
getNetworkAverageController,
);
Expand Down
62 changes: 55 additions & 7 deletions server/src/services/kitchen.outcomes.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import {
KitchenOutcomes,
} from '../models/kitchen.outcomes.model.ts';

const calculateAgeAndRaceDistributions = async (year: number) => {
const calculateAgeAndRaceDistributions = async (
year: number,
mealType: string,
mealRange: string,
) => {
try {
console.log(
'calculating age and race distribution service for year:',
Expand All @@ -13,9 +17,28 @@ const calculateAgeAndRaceDistributions = async (year: number) => {
const startDate = new Date(Date.UTC(year, 0, 1));
const endDate = new Date(Date.UTC(year + 1, 0, 1));

const outcomes = await KitchenOutcomes.find({
const matchConditions: any = {
year: { $gte: startDate, $lt: endDate },
});
};

if (mealType !== 'All') {
matchConditions.typeOfMealsServed = { $in: [mealType] };
}

if (mealRange !== 'All') {
if (mealRange.includes('+')) {
const minRange = parseInt(mealRange.replace('+', ''), 10);
matchConditions.hungerReliefsMealsServed = { $gte: minRange };
} else {
const [minRange, maxRange] = mealRange.split('-').map(Number);
matchConditions.hungerReliefsMealsServed = {
$gte: minRange,
...(maxRange && { $lte: maxRange }),
};
}
}

const outcomes = await KitchenOutcomes.find(matchConditions);

let totalMealsAdults = 0;
let totalMealsInfants = 0;
Expand Down Expand Up @@ -124,6 +147,8 @@ export { calculateAgeAndRaceDistributions };
const getNetworkAverage = async (
field: string,
year: number,
mealType: string,
mealRange: string,
): Promise<number | null> => {
const startDate = new Date(Date.UTC(year, 0, 1));
const endDate = new Date(Date.UTC(year + 1, 0, 1));
Expand All @@ -134,13 +159,36 @@ const getNetworkAverage = async (
year,
startDate,
endDate,
mealType,
mealRange,
});
const matchConditions: any = {
year: { $gte: startDate, $lt: endDate },
[field]: { $exists: true, $ne: NaN },
};

if (mealType !== 'All') {
matchConditions.typeOfMealsServed = { $in: [mealType] };
}

if (mealRange !== 'All') {
if (mealRange.includes('+')) {
const minRange = parseInt(mealRange.replace('+', ''), 10);
matchConditions.hungerReliefsMealsServed = { $gte: minRange };
} else {
const [minRange, maxRange] = mealRange.split('-').map(Number);
matchConditions.hungerReliefsMealsServed = {
$gte: minRange,
...(maxRange && { $lte: maxRange }),
};
}
}

console.log('Service - Match conditions:', matchConditions);

const result = await KitchenOutcomes.aggregate([
{
$match: {
year: { $gte: startDate, $lt: endDate },
[field]: { $exists: true, $ne: NaN },
},
$match: matchConditions,
},
{
$group: {
Expand Down

0 comments on commit f5fc00c

Please sign in to comment.