Skip to content

Commit

Permalink
Merge pull request #19 from vitorrsousaa/feature/GODIET-71-planning-m…
Browse files Browse the repository at this point in the history
…eal-implements-method-to-save-new-name-for-each-food-when-creating-a-plan

Feature/godiet 71 planning meal implements method to save new name for each food when creating a plan
  • Loading branch information
vitorrsousaa authored Mar 23, 2024
2 parents 5648c24 + 90b3230 commit c5caf2c
Show file tree
Hide file tree
Showing 31 changed files with 904 additions and 110 deletions.
152 changes: 152 additions & 0 deletions .scaffolding/component.vsc-template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
(function Template() {
const toPascalCase = (str) =>
str
.replace(/(?:^\w|[A-Z]|\b\w)/g, (fl) => fl.toUpperCase())
.replace(/\W+/g, '');

const toCamelCase = (str) =>
toPascalCase(str).replace(/^./, (firstLetter) => firstLetter.toLowerCase());

return {
userInputs: [
{
title: 'Component page name',
argumentName: 'name',
defaultValue: 'Sample',
},
],
template: [
{
type: 'folder',
name: (inputs) => `${toPascalCase(inputs.name)}`,
children: [
{
type: 'file',
name: 'index.ts',
content: (inputs) => `import { ${toPascalCase(
inputs.name
)}, ${toPascalCase(
inputs.name
)}Props } from './${toCamelCase(inputs.name)}';
export { ${toPascalCase(inputs.name)} };
export type { ${toPascalCase(inputs.name)}Props };
`,
},
{
type: 'file',
name: (inputs) => `${toCamelCase(inputs.name)}.tsx`,
content: (
inputs
) => `import { use${toPascalCase(inputs.name)}Hook } from './${toCamelCase(inputs.name)}.hook';
export interface ${toPascalCase(inputs.name)}Props {
data: string;
}
export function ${toPascalCase(inputs.name)}(props: ${toPascalCase(inputs.name)}Props) {
const { data } = props;
const { state } = use${toPascalCase(inputs.name)}Hook(props);
return (
<div>
<h1>${toPascalCase(inputs.name)}</h1>
{data} {state}
</div>
);
}
`,
},
{
type: 'file',
name: (inputs) => `${toCamelCase(inputs.name)}.hook.ts`,
content: (inputs) => `import React from 'react';
import { ${toPascalCase(inputs.name)}Props } from './${toCamelCase(inputs.name)}';
export function use${toPascalCase(inputs.name)}Hook(props: ${toPascalCase(inputs.name)}Props) {
const { data } = props;
const [state] = React.useState(data);
return {
state,
};
}
`,
},
{
type: 'file',
name: (inputs) => `${toCamelCase(inputs.name)}.spec.tsx`,
content: (inputs) => `
import {
render,
renderHook,
ReturnRenderHookType,
ReturnRenderType,
} from '@testing-react';
import { clearAllMocks } from '@testing-suit';
import { ${toPascalCase(inputs.name)}, ${toPascalCase(inputs.name)}Props } from './${toCamelCase(inputs.name)}';
import { use${toPascalCase(inputs.name)}Hook } from './${toCamelCase(inputs.name)}.hook';
describe('${toPascalCase(inputs.name)}', () => {
beforeEach(() => {
clearAllMocks();
});
describe('render', () => {
let rendered: ReturnRenderType;
beforeEach(() => {
clearAllMocks();
});
afterEach(() => {
rendered.unmount();
});
it('Should render the view with default props', () => {
// Arrange
// Act
rendered = render(<${toPascalCase(inputs.name)} data={'0'} />);
// Assert
expect(rendered.getByText('${toPascalCase(inputs.name)}'));
});
});
describe('hook', () => {
let rendered: ReturnRenderHookType<typeof use${toPascalCase(inputs.name)}Hook>;
beforeEach(() => {
clearAllMocks();
});
afterEach(() => {
rendered.unmount();
});
it('Should render the hook with default props', () => {
// Arrange
const props: ${toPascalCase(inputs.name)}Props = {
data: 'teste',
};
// Act
rendered = renderHook(() => use${toPascalCase(inputs.name)}Hook(props));
// Assert
expect(rendered.result.current.state).toEqual('teste');
});
});
});
`,
},
],
},
],
};
});
4 changes: 2 additions & 2 deletions .scaffolding/page.vsc-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
name: 'index.ts',
content: (inputs) => `import { ${toPascalCase(
inputs.name
)}Controller } from './controller';
)} } from './${toCamelCase(inputs.name)}';
export { ${toPascalCase(inputs.name)}Controller };
export { ${toPascalCase(inputs.name)} };
`,
},
{
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-scroll-area": "^1.0.5",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2",
Expand All @@ -45,6 +46,7 @@
"axios": "^1.6.8",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"cmdk": "0.2.1",
"date-fns": "^3.3.1",
"jspdf": "^2.5.1",
"lodash": "^4.17.21",
Expand All @@ -60,6 +62,7 @@
"tailwind-merge": "^2.2.2",
"tailwindcss": "^3.4.1",
"tailwindcss-animate": "^1.0.7",
"use-debounce": "^10.0.0",
"zod": "^3.22.4"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions src/app/entities/planningMeal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface TMealFood {
qty: number;
options: [];
food: TFood;
name: string;
}

export interface TMeal {
Expand Down
4 changes: 3 additions & 1 deletion src/app/services/planningMeal/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface TCreatePlanningMeal {
time: string;
mealFoods: {
foodId: string;
name: string;
qty: number;
measure: {
name: string;
Expand Down Expand Up @@ -43,7 +44,8 @@ function mapper(planningMeal: TCreatePlanningMealDTO): TCreatePlanningMeal {
time: meal.time,
name: meal.name,
mealFoods: meal.mealFoods.map((mealFood) => ({
foodId: mealFood.id,
foodId: mealFood.foodId,
name: mealFood.name,
qty: mealFood.qty,
measure: mealFood.measure,
options: [],
Expand Down
4 changes: 2 additions & 2 deletions src/app/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export interface PageStatus {
/**
* Interface que define o retorno inicial de um hook.
*/
interface DefaultReturnHookPage {
interface IBaseReturnHook {
/**
* O status da página, incluindo isLoading, isError e noData.
*/
Expand All @@ -33,4 +33,4 @@ interface DefaultReturnHookPage {
*
* @template T - Tipo dos outros itens específicos do usuário.
*/
export type ReturnHookPage<T> = DefaultReturnHookPage & T;
export type ReturnHookPage<T> = IBaseReturnHook & T;
2 changes: 1 addition & 1 deletion src/view/components/CardMeal/Options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function Options(props: OptionsProps) {
className
)}
>
{mealFood.food.name} - {mealFood.qty} {mealFood.measure.name}
{mealFood.name} - {mealFood.qty} {mealFood.measure.name}
</small>
</div>
<div className="flex w-full flex-col gap-2">
Expand Down
5 changes: 2 additions & 3 deletions src/view/pages/CreatePlanning/CreatePlanning.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as z from 'zod';

export const CreateMealFoodSchema = z.object({
name: z.string(),
id: z.string().uuid(),
foodId: z.string().uuid(),
qty: z.number().min(1),
measure: z.object({
name: z.string(),
Expand Down Expand Up @@ -79,7 +79,7 @@ export function useCreatePlanningHook() {
planningMeal: data,
});

toast.success('Plano alimentar criado com sucesso!');
toast.success('Plano alimentar criado!');
} catch (error) {
toast.error('Erro ao criar o plano alimentar');
} finally {
Expand Down Expand Up @@ -109,7 +109,6 @@ export function useCreatePlanningHook() {
);

return {
control,
methods,
errors,
meals: watchMeals,
Expand Down
3 changes: 0 additions & 3 deletions src/view/pages/CreatePlanning/CreatePlanning.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Button } from '@godiet-ui/Button';
import { Input } from '@godiet-ui/Input';

import { DevTool } from '@hookform/devtools';
import { PlusIcon } from '@radix-ui/react-icons';
import { FormProvider } from 'react-hook-form';

Expand All @@ -10,7 +9,6 @@ import { useCreatePlanningHook } from './CreatePlanning.hook';

export function CreatePlanning() {
const {
control,
methods,
errors,
meals,
Expand All @@ -23,7 +21,6 @@ export function CreatePlanning() {

return (
<FormProvider {...methods}>
<DevTool control={control} />
<form>
<div className="flex flex-col gap-4">
<h3 className="pb-2 text-lg font-bold text-foreground">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { useCallback, useMemo, useReducer, useState } from 'react';

import { TCreatePlanningMealDTO } from '@godiet-pages/CreatePlanning/CreatePlanning.hook';
import {
CreateMealFoodSchema,
TCreatePlanningMealDTO,
} from '@godiet-pages/CreatePlanning/CreatePlanning.hook';

import { useFieldArray, useFormContext, useWatch } from 'react-hook-form';
import * as z from 'zod';

import { CreateMealProps } from './CreateMeal';

Expand All @@ -17,6 +21,10 @@ interface FoodsByMeal {
name: string;
}

type TSelectedFoodToEdit = z.infer<typeof CreateMealFoodSchema> & {
mealFoodIndex: number;
};

export function useCreateMealHook(props: CreateMealProps) {
const { mealIndex } = props;

Expand Down Expand Up @@ -50,12 +58,8 @@ export function useCreateMealHook(props: CreateMealProps) {
null
);

const [selectedFoodToEdit, setSelectedFoodToEdit] = useState<{
id: string;
measure: { name: string; qty: number };
qty: number;
mealFoodIndex: number;
} | null>(null);
const [selectedFoodToEdit, setSelectedFoodToEdit] =
useState<TSelectedFoodToEdit | null>(null);

const { register, control } = useFormContext<TCreatePlanningMealDTO>();

Expand All @@ -78,7 +82,7 @@ export function useCreateMealHook(props: CreateMealProps) {
const initialFoodsByMeal: FoodsByMeal[] = [];
watchMeal.mealFoods.forEach((food) => {
initialFoodsByMeal.push({
id: food.id,
id: food.foodId,
measure: food.measure,
qty: food.qty,
prot: 0.6 * 20,
Expand All @@ -95,7 +99,7 @@ export function useCreateMealHook(props: CreateMealProps) {
const generateHashKey = useMemo(() => {
if (!selectedFoodToEdit) return 'food-to-edit';

const hashId = selectedFoodToEdit.id;
const hashId = selectedFoodToEdit.foodId;
const hashMeasureName = selectedFoodToEdit.measure.name
.trim()
.replace(' ', '-');
Expand All @@ -120,10 +124,11 @@ export function useCreateMealHook(props: CreateMealProps) {
toggleSelectedMealIndex(mealIndex);

setSelectedFoodToEdit({
id: selectedFood.id,
foodId: selectedFood.id,
measure: selectedFood.measure,
qty: selectedFood.qty,
mealFoodIndex: mealFoodIndex,
name: selectedFood.name,
});
toggleModalEditFoodOpen();
},
Expand Down
14 changes: 10 additions & 4 deletions src/view/pages/CreatePlanning/components/CreateMeal/CreateMeal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,16 @@ export function CreateMeal(props: CreateMealProps) {

<Separator />

<Card.Footer className="flex flex-col gap-2">
<h1 className="text-md mt-4 font-semibold text-muted-foreground">
Alimentos selecionados
</h1>
<Card.Footer className="flex flex-col gap-4">
<div className="text-center">
<h1 className="text-md mt-4 font-semibold text-muted-foreground">
Alimentos selecionados
</h1>
<small className="text-muted-foreground">
Você pode editar o título dos alimentos selecionados na tabela
abaixo.
</small>
</div>
<TableFoodsByMeal
mealIndex={mealIndex}
onOpenModalRemove={handleOpenModalRemoveFood}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ export function useTableFoodsByMealHook(props: TableFoodsByMealProps) {
const initialFoodsByMeal: FoodsByMeal[] = [];
watchMeal.mealFoods.forEach((food) => {
const selectedFood = foods.find(
(foodDatabase) => foodDatabase.id === food.id
(foodDatabase) => foodDatabase.id === food.foodId
);

if (!selectedFood) return;

const mealFoodCalculated = calculateMealFoods({
food: selectedFood,
food: {
...selectedFood,
name: food.name,
},
measure: food.measure,
qty: food.qty,
});
Expand Down
Loading

0 comments on commit c5caf2c

Please sign in to comment.