Refactor #2
This commit is contained in:
parent
ee2f08cbfc
commit
ec28531df9
15 changed files with 219 additions and 31 deletions
|
|
@ -16,7 +16,7 @@ Last updated: 2025-10-18
|
||||||
- [x] Extract router into `src/router/index.js` with named routes
|
- [x] Extract router into `src/router/index.js` with named routes
|
||||||
- [x] Add route meta `requiresAuth` and a global auth guard
|
- [x] Add route meta `requiresAuth` and a global auth guard
|
||||||
- [x] Remove auth-redirect from `App.vue` (handled by guard instead)
|
- [x] Remove auth-redirect from `App.vue` (handled by guard instead)
|
||||||
- [ ] Convert top-level nav to use route names consistently (optional)
|
- [x] Convert top-level nav to use route names consistently (optional)
|
||||||
|
|
||||||
Outcome: Routing logic is centralized and testable; pages redirect consistently based on auth.
|
Outcome: Routing logic is centralized and testable; pages redirect consistently based on auth.
|
||||||
|
|
||||||
|
|
@ -24,9 +24,9 @@ Outcome: Routing logic is centralized and testable; pages redirect consistently
|
||||||
- [x] Add `src/api/http.js` wrapper for JSON fetch with error handling and env-based base URL
|
- [x] Add `src/api/http.js` wrapper for JSON fetch with error handling and env-based base URL
|
||||||
- [x] Add `src/api/mappers/mealMapper.js` to normalize Meal data (dates)
|
- [x] Add `src/api/mappers/mealMapper.js` to normalize Meal data (dates)
|
||||||
- [x] Add `src/api/meals.js` and migrate MealPlan API calls (get upcoming, mark consumed, delete)
|
- [x] Add `src/api/meals.js` and migrate MealPlan API calls (get upcoming, mark consumed, delete)
|
||||||
- [ ] Create `src/api/recipes.js` and migrate recipe endpoints
|
- [x] Create `src/api/recipes.js` and migrate recipe endpoints
|
||||||
- [ ] Create `src/api/shopping.js` and migrate shopping endpoints
|
- [x] Create `src/api/shopping.js` and migrate shopping endpoints
|
||||||
- [ ] Create `src/api/auth.js` and migrate auth endpoints
|
- [x] Create `src/api/auth.js` and migrate auth endpoints
|
||||||
|
|
||||||
Outcome: Feature modules call cohesive services; logic for mapping/normalization is isolated and testable.
|
Outcome: Feature modules call cohesive services; logic for mapping/normalization is isolated and testable.
|
||||||
|
|
||||||
|
|
@ -60,3 +60,6 @@ Outcome: Confidence in refactors and easier onboarding.
|
||||||
- Removed `App.vue` auth redirect
|
- Removed `App.vue` auth redirect
|
||||||
- Added `api/http.js`, `api/mappers/mealMapper.js`, `api/meals.js`
|
- Added `api/http.js`, `api/mappers/mealMapper.js`, `api/meals.js`
|
||||||
- Updated `MealPlanPage.vue` to use meals API
|
- Updated `MealPlanPage.vue` to use meals API
|
||||||
|
- Added `api/mappers/recipeMapper.js`, `api/recipes.js`; updated recipes components
|
||||||
|
- Added `api/mappers/shoppingListMapper.js`, `api/shopping.js`; updated shopping components
|
||||||
|
- Added `api/auth.js` and `api/persons.js`; router uses auth API
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
<div>
|
<div>
|
||||||
<ul class="nav">
|
<ul class="nav">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<router-link class="nav-link" to="/recipes" active-class="active">Recipes</router-link>
|
<router-link class="nav-link" :to="{ name: 'recipes' }" active-class="active">Recipes</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<router-link class="nav-link" to="/mealplan" active-class="active">Meal Plan</router-link>
|
<router-link class="nav-link" :to="{ name: 'mealplan' }" active-class="active">Meal Plan</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<router-link class="nav-link" to="/shopping" active-class="active">Shopping</router-link>
|
<router-link class="nav-link" :to="{ name: 'shopping' }" active-class="active">Shopping</router-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
21
src/api/auth.js
Normal file
21
src/api/auth.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { http } from './http'
|
||||||
|
|
||||||
|
let cachedUser = null
|
||||||
|
|
||||||
|
export async function currentUser() {
|
||||||
|
if (cachedUser) return cachedUser
|
||||||
|
// Try a refresh if a cookie exists (browser will send it automatically)
|
||||||
|
try {
|
||||||
|
const user = await http.post('/auth/refresh')
|
||||||
|
cachedUser = user
|
||||||
|
} catch (_) {
|
||||||
|
cachedUser = null
|
||||||
|
}
|
||||||
|
return cachedUser
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function login(username) {
|
||||||
|
const user = await http.post('/auth/login', { username })
|
||||||
|
cachedUser = user
|
||||||
|
return user
|
||||||
|
}
|
||||||
15
src/api/mappers/recipeMapper.js
Normal file
15
src/api/mappers/recipeMapper.js
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
function toDate(value) {
|
||||||
|
return value ? new Date(value) : value
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapRecipe(recipe) {
|
||||||
|
if (!recipe) return recipe
|
||||||
|
recipe.date_created = toDate(recipe.date_created)
|
||||||
|
recipe.date_hidden = toDate(recipe.date_hidden)
|
||||||
|
return recipe
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapRecipes(list) {
|
||||||
|
if (!Array.isArray(list)) return []
|
||||||
|
return list.map(mapRecipe)
|
||||||
|
}
|
||||||
69
src/api/mappers/shoppingListMapper.js
Normal file
69
src/api/mappers/shoppingListMapper.js
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { mapMeal } from './mealMapper'
|
||||||
|
import { mapRecipe } from './recipeMapper'
|
||||||
|
|
||||||
|
function toDate(value) {
|
||||||
|
return value ? new Date(value) : value
|
||||||
|
}
|
||||||
|
|
||||||
|
function attachItemRefs(items, { ingredients_lookup, meals_lookup, recipes_lookup, shopping_list_lookup }) {
|
||||||
|
if (!Array.isArray(items)) return
|
||||||
|
for (const item of items) {
|
||||||
|
if (item.ingredient_id && ingredients_lookup) item.ingredient = ingredients_lookup[item.ingredient_id]
|
||||||
|
if (item.meal_id && meals_lookup) item.meal = meals_lookup[item.meal_id]
|
||||||
|
if (item.recipe_id && recipes_lookup) item.recipe = recipes_lookup[item.recipe_id]
|
||||||
|
if (item.list_id && shopping_list_lookup) item.list = shopping_list_lookup[item.list_id]
|
||||||
|
if (item.created_date) item.created_date = toDate(item.created_date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapPurchasedShoppingList(dto) {
|
||||||
|
if (!dto) return dto
|
||||||
|
// Map lookups
|
||||||
|
if (dto.meals_lookup) {
|
||||||
|
for (const [k, v] of Object.entries(dto.meals_lookup)) dto.meals_lookup[k] = mapMeal(v)
|
||||||
|
}
|
||||||
|
if (dto.recipes_lookup) {
|
||||||
|
for (const [k, v] of Object.entries(dto.recipes_lookup)) dto.recipes_lookup[k] = mapRecipe(v)
|
||||||
|
}
|
||||||
|
if (dto.ingredients_lookup) {
|
||||||
|
// no date fields expected on ingredient based on current usage
|
||||||
|
}
|
||||||
|
if (dto.list) {
|
||||||
|
if (dto.list.created_date) dto.list.created_date = toDate(dto.list.created_date)
|
||||||
|
if (Array.isArray(dto.list.items)) {
|
||||||
|
attachItemRefs(dto.list.items, {
|
||||||
|
ingredients_lookup: dto.ingredients_lookup,
|
||||||
|
meals_lookup: dto.meals_lookup,
|
||||||
|
recipes_lookup: dto.recipes_lookup,
|
||||||
|
shopping_list_lookup: { [dto.list.id]: dto.list },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dto
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapCurrentShoppingList(dto) {
|
||||||
|
if (!dto) return dto
|
||||||
|
if (dto.meals_lookup) {
|
||||||
|
for (const [k, v] of Object.entries(dto.meals_lookup)) dto.meals_lookup[k] = mapMeal(v)
|
||||||
|
}
|
||||||
|
if (dto.recipes_lookup) {
|
||||||
|
for (const [k, v] of Object.entries(dto.recipes_lookup)) dto.recipes_lookup[k] = mapRecipe(v)
|
||||||
|
}
|
||||||
|
if (dto.shopping_list_lookup) {
|
||||||
|
for (const [, v] of Object.entries(dto.shopping_list_lookup)) {
|
||||||
|
if (v?.created_date) v.created_date = toDate(v.created_date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const lookups = {
|
||||||
|
ingredients_lookup: dto.ingredients_lookup,
|
||||||
|
meals_lookup: dto.meals_lookup,
|
||||||
|
recipes_lookup: dto.recipes_lookup,
|
||||||
|
shopping_list_lookup: dto.shopping_list_lookup,
|
||||||
|
}
|
||||||
|
attachItemRefs(dto.outstanding_items, lookups)
|
||||||
|
attachItemRefs(dto.requested_meals, lookups)
|
||||||
|
attachItemRefs(dto.purchased_items, lookups)
|
||||||
|
return dto
|
||||||
|
}
|
||||||
5
src/api/persons.js
Normal file
5
src/api/persons.js
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { http } from './http'
|
||||||
|
|
||||||
|
export async function getPersonsInHome() {
|
||||||
|
return http.get('/persons')
|
||||||
|
}
|
||||||
36
src/api/recipes.js
Normal file
36
src/api/recipes.js
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { http } from './http'
|
||||||
|
import { mapRecipe, mapRecipes } from './mappers/recipeMapper'
|
||||||
|
|
||||||
|
export async function searchRecipes(query) {
|
||||||
|
const recipes = await http.get(`/recipes?q=${encodeURIComponent(query)}`)
|
||||||
|
return mapRecipes(recipes)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getRecipe(id) {
|
||||||
|
const recipe = await http.get(`/recipes/${encodeURIComponent(id)}`)
|
||||||
|
return mapRecipe(recipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function saveRecipe(recipe) {
|
||||||
|
const saved = await http.post('/recipes', recipe)
|
||||||
|
return mapRecipe(saved)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteRecipe(id) {
|
||||||
|
return http.del(`/recipes/${encodeURIComponent(id)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function parseRecipe(url) {
|
||||||
|
const recipe = await http.get(`/recipes/parse?url=${encodeURIComponent(url)}`)
|
||||||
|
return mapRecipe(recipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function parseIngredients(lines) {
|
||||||
|
const params = lines.map(line => `ingredients=${encodeURIComponent(line)}`).join('&')
|
||||||
|
return http.get(`/recipes/ingredients/parse?${params}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function parseProduct(ingredient, url) {
|
||||||
|
const body = { url, tags: [ingredient.name, ingredient.line] }
|
||||||
|
return http.post('/products', body)
|
||||||
|
}
|
||||||
38
src/api/shopping.js
Normal file
38
src/api/shopping.js
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { http } from './http'
|
||||||
|
import { mapPurchasedShoppingList, mapCurrentShoppingList } from './mappers/shoppingListMapper'
|
||||||
|
|
||||||
|
export async function getMyShoppingList() {
|
||||||
|
const ingredients = await http.get('/shopping/current/me/ingredients')
|
||||||
|
return ingredients
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function saveMyShoppingList(list) {
|
||||||
|
const ingredients = await http.post('/shopping/current/me/ingredients', list)
|
||||||
|
return ingredients
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getShoppingList(id) {
|
||||||
|
const dto = await http.get(`/shopping/${encodeURIComponent(id)}`)
|
||||||
|
const mapped = mapPurchasedShoppingList(dto)
|
||||||
|
return mapped.list
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getCurrentShoppingList() {
|
||||||
|
const dto = await http.get('/shopping/current')
|
||||||
|
return mapCurrentShoppingList(dto)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function purchaseShoppingList(completedRequests) {
|
||||||
|
const dto = await http.post('/shopping/', { items: completedRequests })
|
||||||
|
const mapped = mapPurchasedShoppingList(dto)
|
||||||
|
return mapped.list
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function requestMeal(mealId) {
|
||||||
|
const items = await http.post('/shopping/current/meals/me', { meal_id: mealId })
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function unrequestMeal(mealId) {
|
||||||
|
await http.del(`/shopping/current/meals/${encodeURIComponent(mealId)}`)
|
||||||
|
}
|
||||||
|
|
@ -75,7 +75,7 @@ li > div {
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import data from '@/data.js'
|
import { parseProduct, parseIngredients } from '@/api/recipes'
|
||||||
import IngredientLine from './IngredientLine.vue'
|
import IngredientLine from './IngredientLine.vue'
|
||||||
import CompactParsedIngredient from './CompactParsedIngredient.vue'
|
import CompactParsedIngredient from './CompactParsedIngredient.vue'
|
||||||
|
|
||||||
|
|
@ -90,11 +90,11 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async updateProduct(ingredient, product_link) {
|
async updateProduct(ingredient, product_link) {
|
||||||
const product = await data.parseProduct(ingredient, product_link);
|
const product = await parseProduct(ingredient, product_link);
|
||||||
this.$emit('on-update-ingredient', ingredient, { ...ingredient, product });
|
this.$emit('on-update-ingredient', ingredient, { ...ingredient, product });
|
||||||
},
|
},
|
||||||
async updateIngredient(ingredient, line) {
|
async updateIngredient(ingredient, line) {
|
||||||
const newIngredients = await data.parseIngredients([line]);
|
const newIngredients = await parseIngredients([line]);
|
||||||
this.$emit('on-update-ingredient', ingredient, newIngredients[0]);
|
this.$emit('on-update-ingredient', ingredient, newIngredients[0]);
|
||||||
},
|
},
|
||||||
toggleEditing() {
|
toggleEditing() {
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ input.recipe-name {
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import alert from '@/alert.js'
|
import alert from '@/alert.js'
|
||||||
import data from '@/data.js'
|
import { getRecipe, parseRecipe, saveRecipe, deleteRecipe as deleteRecipeApi } from '@/api/recipes'
|
||||||
import EditableIngredientsPanel from '@/components/ingredients/EditableIngredientsPanel.vue'
|
import EditableIngredientsPanel from '@/components/ingredients/EditableIngredientsPanel.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -101,12 +101,12 @@ export default {
|
||||||
},
|
},
|
||||||
async refreshRecipe() {
|
async refreshRecipe() {
|
||||||
if (this.id >= 0) {
|
if (this.id >= 0) {
|
||||||
this.recipe = await data.getRecipe(this.id);
|
this.recipe = await getRecipe(this.id);
|
||||||
this.link = this.recipe.link;
|
this.link = this.recipe.link;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (this.link) {
|
else if (this.link) {
|
||||||
this.recipe = await data.parseRecipe(this.link);
|
this.recipe = await parseRecipe(this.link);
|
||||||
this.parse_failed = !this.recipe;
|
this.parse_failed = !this.recipe;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -120,7 +120,7 @@ export default {
|
||||||
this.recipe.ingredients = this.recipe.ingredients.filter(i => i != ingredient);
|
this.recipe.ingredients = this.recipe.ingredients.filter(i => i != ingredient);
|
||||||
},
|
},
|
||||||
async saveRecipe() {
|
async saveRecipe() {
|
||||||
const recipe = await data.saveRecipe(this.recipe);
|
const recipe = await saveRecipe(this.recipe);
|
||||||
if (recipe?.id >= 0) {
|
if (recipe?.id >= 0) {
|
||||||
alert.show({ heading: 'Recipe saved', message: 'Your recipe has been saved', type: 'success' });
|
alert.show({ heading: 'Recipe saved', message: 'Your recipe has been saved', type: 'success' });
|
||||||
this.$router.push(`/recipes/${recipe.id}`);
|
this.$router.push(`/recipes/${recipe.id}`);
|
||||||
|
|
@ -144,7 +144,7 @@ export default {
|
||||||
},
|
},
|
||||||
async deleteRecipe() {
|
async deleteRecipe() {
|
||||||
if (confirm('Are you sure you want to delete this recipe?')) {
|
if (confirm('Are you sure you want to delete this recipe?')) {
|
||||||
await data.deleteRecipe(this.recipe.id);
|
await deleteRecipeApi(this.recipe.id);
|
||||||
this.$router.push('/recipes');
|
this.$router.push('/recipes');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import data from '@/data.js'
|
import { searchRecipes } from '@/api/recipes'
|
||||||
import RecipeCard from './RecipeCard.vue';
|
import RecipeCard from './RecipeCard.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -41,7 +41,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async search() {
|
async search() {
|
||||||
this.recipes = await data.searchRecipes(this.searchTerm) ?? this.recipes;
|
this.recipes = await searchRecipes(this.searchTerm) ?? this.recipes;
|
||||||
},
|
},
|
||||||
selectRecipe(recipe) {
|
selectRecipe(recipe) {
|
||||||
this.$emit('select-recipe', recipe);
|
this.$emit('select-recipe', recipe);
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,8 @@ button img {
|
||||||
|
|
||||||
import alert from '@/alert.js'
|
import alert from '@/alert.js'
|
||||||
|
|
||||||
import data from '@/data.js'
|
import { getCurrentShoppingList, purchaseShoppingList, requestMeal, unrequestMeal } from '@/api/shopping'
|
||||||
|
import { getUpcomingMeals } from '@/api/meals'
|
||||||
import { itemsToGroups, groupsToItems, uniqueMeals } from './shopping.js'
|
import { itemsToGroups, groupsToItems, uniqueMeals } from './shopping.js'
|
||||||
|
|
||||||
import MealSelectionList from './MealSelectionList.vue'
|
import MealSelectionList from './MealSelectionList.vue'
|
||||||
|
|
@ -150,7 +151,7 @@ async function saveShoppingList(outstandingItemGroups) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await data.purchaseShoppingList(items);
|
return await purchaseShoppingList(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupsMatch = (a, b) => {
|
const groupsMatch = (a, b) => {
|
||||||
|
|
@ -206,15 +207,15 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async loadData() {
|
async loadData() {
|
||||||
this.upcomingMeals = await data.getUpcomingMeals(this.from, this.to);
|
this.upcomingMeals = await getUpcomingMeals(this.from, this.to);
|
||||||
this.shoppingList = await data.getCurrentShoppingList();
|
this.shoppingList = await getCurrentShoppingList();
|
||||||
},
|
},
|
||||||
async mealSelected(meal) {
|
async mealSelected(meal) {
|
||||||
await data.requestMeal(meal.id);
|
await requestMeal(meal.id);
|
||||||
await this.loadData();
|
await this.loadData();
|
||||||
},
|
},
|
||||||
async mealUnselected(meal) {
|
async mealUnselected(meal) {
|
||||||
await data.unrequestMeal(meal.id);
|
await unrequestMeal(meal.id);
|
||||||
await this.loadData();
|
await this.loadData();
|
||||||
},
|
},
|
||||||
async markFound() {
|
async markFound() {
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import data from '@/data.js'
|
import { getMyShoppingList, saveMyShoppingList } from '@/api/shopping'
|
||||||
|
|
||||||
import EditableIngredientsPanel from '@/components/ingredients/EditableIngredientsPanel.vue'
|
import EditableIngredientsPanel from '@/components/ingredients/EditableIngredientsPanel.vue'
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ export default {
|
||||||
return { ingredients: [], person: null }
|
return { ingredients: [], person: null }
|
||||||
},
|
},
|
||||||
async beforeMount() {
|
async beforeMount() {
|
||||||
const person = await data.currentUser();
|
const person = await this.$router.app?.config?.globalProperties?.$user || null;
|
||||||
if (!person)
|
if (!person)
|
||||||
return this.$router.push({ name: 'login' });
|
return this.$router.push({ name: 'login' });
|
||||||
|
|
||||||
|
|
@ -57,8 +57,8 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
async updateShoppingList(save = false) {
|
async updateShoppingList(save = false) {
|
||||||
const new_ingredients = save ?
|
const new_ingredients = save ?
|
||||||
await data.saveMyShoppingList(this.ingredients) :
|
await saveMyShoppingList(this.ingredients) :
|
||||||
await data.getMyShoppingList();
|
await getMyShoppingList();
|
||||||
|
|
||||||
this.ingredients = new_ingredients;
|
this.ingredients = new_ingredients;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
import { ago } from '@/dateformats.js'
|
import { ago } from '@/dateformats.js'
|
||||||
|
|
||||||
import data from '@/data.js'
|
import { getShoppingList } from '@/api/shopping'
|
||||||
import { itemsToGroups, uniqueMeals } from './shopping.js'
|
import { itemsToGroups, uniqueMeals } from './shopping.js'
|
||||||
|
|
||||||
import MealSelectionList from './MealSelectionList.vue'
|
import MealSelectionList from './MealSelectionList.vue'
|
||||||
|
|
@ -60,7 +60,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async beforeMount() {
|
async beforeMount() {
|
||||||
this.shoppingList = await data.getShoppingList(this.id);
|
this.shoppingList = await getShoppingList(this.id);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
ago
|
ago
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import { createAppRouter } from '@/router'
|
import { createAppRouter } from '@/router'
|
||||||
import data from '@/data.js'
|
import { currentUser } from '@/api/auth'
|
||||||
|
|
||||||
// Create the router with an auth callback to check current user
|
// Create the router with an auth callback to check current user
|
||||||
const router = createAppRouter(() => data.currentUser())
|
const router = createAppRouter(() => currentUser())
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue