Skip to content

Commit

Permalink
feat: Add ingredient groups and upgrade dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
sopelj committed Aug 23, 2024
1 parent fcfb781 commit 9cae428
Show file tree
Hide file tree
Showing 8 changed files with 437 additions and 380 deletions.
6 changes: 6 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ COPY --from=build-image /opt/venv /opt/venv
# Install Deps (translations and SSR)
RUN apk add --no-cache bash nodejs yarn gettext libpq-dev libldap


# Entrypoint
COPY ./docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
Expand All @@ -37,6 +38,11 @@ COPY ./docker/run-dev-servers.sh /run-dev-servers.sh
RUN chmod +x /run-dev-servers.sh

ENV PATH=/opt/venv/bin:$PATH

# Set DB variables in default shell so docker exec -it will have it
ENV ENV=/home/django/.ashrc
RUN echo 'export DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_DB_HOST}/${POSTGRES_DB}"' > "$ENV"

WORKDIR /app

EXPOSE 8000
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-vue": "^9.27.0",
"happy-dom": "^14.12.3",
"happy-dom": "^15.0.0",
"postcss": "^8.4.39",
"prettier": "^3.3.3",
"sass": "^1.77.8",
Expand Down
10 changes: 9 additions & 1 deletion recipe_repo/recipes/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from rest_framework.serializers import DurationField, IntegerField, ModelSerializer, SlugRelatedField

from ..users.serializers import UserSerializer
from .models import Category, Ingredient, NutritionInformation, Recipe, Source, YieldUnit
from .models import Category, Ingredient, IngredientGroup, NutritionInformation, Recipe, Source, YieldUnit

if TYPE_CHECKING:
from .models import IngredientQualifier, Step
Expand Down Expand Up @@ -50,6 +50,12 @@ class Meta:
fields = ("id", "amount_display", "food_display", "optional", "note", "qualifier", "group_id")


class IngredientGroupSerializer(ModelSerializer[IngredientGroup]):
class Meta:
model = IngredientGroup
fields = ("id", "name")


class RecipeListSerializer(ModelSerializer[Recipe]):
num_ratings = IntegerField()
avg_rating = IntegerField(allow_null=True)
Expand All @@ -71,6 +77,7 @@ class RecipeSerializer(RecipeListSerializer):
steps: SlugRelatedField[Step] = SlugRelatedField(many=True, read_only=True, slug_field="text")
source = SourceSerializer(read_only=True) # type: ignore[assignment]
parent_recipes = RelatedRecipeSerializer(many=True, read_only=True)
ingredient_groups = IngredientGroupSerializer(many=True, read_only=True)
yield_unit = YieldUnitSerializer(read_only=True)
nutrition = NutritionSerializer(read_only=True)
added_by = UserSerializer(read_only=True)
Expand All @@ -89,6 +96,7 @@ class Meta:
"nutrition",
"num_ratings",
"avg_rating",
"ingredient_groups",
"parent_recipes",
"steps",
"source",
Expand Down
67 changes: 67 additions & 0 deletions src/components/IngredientList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<script setup lang="ts">
import type { Ingredient, IngredientGroup } from "@/types/recipes";
import { computed } from "vue";
import { useI18n } from "vue-i18n";
const props = defineProps<{ ingredients: Ingredient[]; groups: IngredientGroup[] }>();
const { t } = useI18n();
const groupMapping = computed(() =>
props.groups.reduce((acc: Record<string, string>, group: IngredientGroup) => {
acc[group.id.toString()] = group.name;
return acc;
}, {}),
);
const groupedIngredients = computed(() =>
Object.groupBy(props.ingredients, ({ group_id }) =>
group_id ? groupMapping.value[group_id.toString()] : "",
),
);
</script>

<template>
<div
v-for="[group, groupIngredients] in Object.entries(groupedIngredients)"
:key="group"
>
<h3
v-if="group"
class="pt-4"
>
{{ group }}
</h3>
<ul>
<li
v-for="ingredient in groupIngredients"
:key="ingredient.id"
itemprop="recipeIngredient"
>
<I18nT
keypath="recipe.ingredient"
tag="span"
>
<template #amount>{{ ingredient.amount_display }}</template>
<template #ingredient>
<strong>{{ ingredient.food_display }}</strong>
</template>
</I18nT>
<span
v-if="ingredient.qualifier"
class="qualifier"
>
{{ t("recipe.ingredient_qualifier", { qualifier: ingredient.qualifier }) }}
</span>
<span
v-if="ingredient.optional"
class="optional"
>
{{ t("recipe.ingredient_optional") }}
</span>
<span v-if="ingredient.note">{{ t("recipe.ingredient_note", { note: ingredient.note }) }}</span>
</li>
</ul>
</div>
</template>
60 changes: 21 additions & 39 deletions src/pages/RecipeDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useShare } from "@/composables/share";
import DescriptionItem from "@/components/DescriptionItem.vue";
import FavouriteForm from "@/components/FavouriteForm.vue";
import IngredientList from "@/components/IngredientList.vue";
import KeepAwake from "@/components/KeepAwake.vue";
import NutritionalInformation from "@/components/NutritionalInformation.vue";
import RatingForm from "@/components/RatingForm.vue";
Expand Down Expand Up @@ -152,7 +153,7 @@ const shareRecipe = async () => {
:servings="servings"
class="mt-4"
/>
<div class="ingredients">
<div class="mt-4">
<Card>
<template #title>
<div class="flex flex-row items-center">
Expand All @@ -161,45 +162,26 @@ const shareRecipe = async () => {
</div>
</template>
<template #content>
<ul>
<li
v-for="r in recipe.parent_recipes || []"
:key="r.slug"
>
<Link
:href="t('routes.recipe_details', { slug: r.slug })"
class="underline"
>{{ r.name }}</Link
<div v-if="recipe.parent_recipes?.length">
<ul>
<li
v-for="r in recipe.parent_recipes"
:key="r.slug"
itemprop="recipeIngredient"
>
</li>
<li
v-for="ingredient in ingredients"
:key="ingredient.id"
>
<I18nT
keypath="recipe.ingredient"
tag="span"
>
<template #amount>{{ ingredient.amount_display }}</template>
<template #ingredient>
<strong>{{ ingredient.food_display }}</strong>
</template>
</I18nT>
<span
v-if="ingredient.qualifier"
class="qualifier"
>{{ t("recipe.ingredient_qualifier", { qualifier: ingredient.qualifier }) }}</span
>
<span
v-if="ingredient.optional"
class="optional"
>{{ t("recipe.ingredient_optional") }}</span
>
<span v-if="ingredient.note">{{
t("recipe.ingredient_note", { note: ingredient.note })
}}</span>
</li>
</ul>
<Link
:href="t('routes.recipe_details', { slug: r.slug })"
class="underline"
>
{{ r.name }}
</Link>
</li>
</ul>
</div>
<IngredientList
:ingredients="ingredients"
:groups="recipe.ingredient_groups"
/>
</template>
</Card>
</div>
Expand Down
7 changes: 7 additions & 0 deletions src/types/recipes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface NutritionInformation {

export interface Ingredient {
id: number;
group_id: number | null;
amount_display?: string;
food_display: string;
optional: boolean;
Expand All @@ -43,6 +44,11 @@ export interface Source {
value?: string;
}

export interface IngredientGroup {
id: number;
name: string;
}

export interface YieldUnit {
name: string;
name_plural?: string;
Expand All @@ -58,6 +64,7 @@ export interface Recipe extends Omit<RecipeItem, "thumbnail_url"> {
prep_time?: string;
total_time?: string;
source?: Source;
ingredient_groups: IngredientGroup[];
parent_recipes?: BaseRecipe[];
source_value?: string;
nutrition?: NutritionInformation;
Expand Down
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"lib": [
"ES2022",
"ESNext",
"DOM",
"DOM.Iterable"
],
Expand All @@ -22,7 +22,7 @@
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"target": "ES2022",
"target": "ESNext",
"types": [
"vite/client",
"vitest/globals",
Expand Down
Loading

0 comments on commit 9cae428

Please sign in to comment.