Refactor #3
This commit is contained in:
parent
ec28531df9
commit
a6904524db
10 changed files with 78 additions and 13 deletions
12
.editorconfig
Normal file
12
.editorconfig
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
7
.prettierrc.json
Normal file
7
.prettierrc.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"semi": false,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 100,
|
||||
"arrowParens": "always"
|
||||
}
|
||||
|
|
@ -31,14 +31,14 @@ Outcome: Routing logic is centralized and testable; pages redirect consistently
|
|||
Outcome: Feature modules call cohesive services; logic for mapping/normalization is isolated and testable.
|
||||
|
||||
### Phase 3 — Composables (UI-Facing Logic)
|
||||
- [ ] Add `src/composables/useAuth.js` (user ref, ensureAuth)
|
||||
- [x] Add `src/composables/useAuth.js` (user ref, ensureAuth)
|
||||
- [ ] Add `src/composables/useMeals.js` (fetch and mutate meals)
|
||||
- [ ] Refactor pages to use composables and `<script setup>` where appropriate
|
||||
|
||||
Outcome: Components get smaller and easier to read; business logic is reusable.
|
||||
|
||||
### Phase 4 — Tooling and Standards
|
||||
- [ ] Add Prettier config and .editorconfig; wire Prettier with ESLint
|
||||
- [x] Add Prettier config and .editorconfig; wire Prettier with ESLint
|
||||
- [ ] Upgrade ESLint (if/when convenient) and align with Vue 3 rules
|
||||
- [ ] Ensure Volar is used (dev environment) for Vue 3 type intelligence
|
||||
|
||||
|
|
@ -63,3 +63,5 @@ Outcome: Confidence in refactors and easier onboarding.
|
|||
- 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
|
||||
- Added `composables/useAuth.js` and used in `MyShoppingPage.vue`
|
||||
- Added Prettier and EditorConfig
|
||||
|
|
|
|||
|
|
@ -16,3 +16,16 @@ export async function markMealConsumed(mealId) {
|
|||
export async function deleteMeal(mealId) {
|
||||
return http.del(`/meals/${encodeURIComponent(mealId)}`)
|
||||
}
|
||||
|
||||
export async function getMeal(id) {
|
||||
const meal = await http.get(`/meals/${encodeURIComponent(id)}`)
|
||||
return mapMeal(meal)
|
||||
}
|
||||
|
||||
export async function saveMeal(meal) {
|
||||
const hasId = meal.id >= 0
|
||||
const path = hasId ? `/meals/${encodeURIComponent(meal.id)}` : '/meals'
|
||||
const method = hasId ? http.put : http.post
|
||||
const saved = await method(path, meal)
|
||||
return mapMeal(saved)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,3 +3,7 @@ import { http } from './http'
|
|||
export async function getPersonsInHome() {
|
||||
return http.get('/persons')
|
||||
}
|
||||
|
||||
export async function searchPerson(name) {
|
||||
return http.get(`/persons?q=${encodeURIComponent(name)}`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,8 @@ li:nth-child(4) > button {
|
|||
</style>
|
||||
|
||||
<script>
|
||||
import data from '@/data';
|
||||
import { getPersonsInHome } from '@/api/persons';
|
||||
import { login } from '@/api/auth';
|
||||
|
||||
export default {
|
||||
name: 'LoginVue',
|
||||
|
|
@ -89,11 +90,11 @@ export default {
|
|||
}
|
||||
},
|
||||
async beforeMount() {
|
||||
this.persons = await data.getPersonsInHome();
|
||||
this.persons = await getPersonsInHome();
|
||||
},
|
||||
methods: {
|
||||
async login(selectedPerson) {
|
||||
const person = await data.login(selectedPerson.name);
|
||||
const person = await login(selectedPerson.name);
|
||||
if (person?.id >= 0) {
|
||||
this.$router.push(this.redirect);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,9 @@
|
|||
|
||||
<script>
|
||||
|
||||
import data from '@/data.js';
|
||||
import { getMeal, saveMeal } from '@/api/meals';
|
||||
import { getRecipe } from '@/api/recipes';
|
||||
import { currentUser } from '@/api/auth';
|
||||
import alert from '@/alert.js';
|
||||
|
||||
import { ago } from '@/dateformats.js';
|
||||
|
|
@ -96,10 +98,10 @@ export default {
|
|||
},
|
||||
async beforeMount() {
|
||||
if (this.id >= 0) {
|
||||
this.meal = await data.getMeal(this.id);
|
||||
this.meal = await getMeal(this.id);
|
||||
}
|
||||
else {
|
||||
const self = await data.currentUser();
|
||||
const self = await currentUser();
|
||||
this.meal = {...this.meal, chefs: [self], consumers: [self], cleanup: [self], };
|
||||
}
|
||||
},
|
||||
|
|
@ -107,7 +109,7 @@ export default {
|
|||
ago,
|
||||
async selectRecipe(recipe) {
|
||||
// Refetch to get additional details
|
||||
recipe = await data.getRecipe(recipe.id);
|
||||
recipe = await getRecipe(recipe.id);
|
||||
|
||||
if (recipe.created_by) {
|
||||
addPersonIfNotExists(this.meal.chefs, recipe.created_by);
|
||||
|
|
@ -144,7 +146,7 @@ export default {
|
|||
addPersonIfNotExists(this.meal[list], person);
|
||||
},
|
||||
async saveMeal() {
|
||||
const meal = await data.saveMeal(this.meal);
|
||||
const meal = await saveMeal(this.meal);
|
||||
if (meal?.id >= 0) {
|
||||
this.meal = meal;
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@
|
|||
|
||||
<script>
|
||||
import { ref } from 'vue';
|
||||
import data from '@/data.js'
|
||||
import { searchPerson } from '@/api/persons'
|
||||
|
||||
export default {
|
||||
name: 'PersonList',
|
||||
|
|
@ -142,7 +142,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
async updateSearchResults() {
|
||||
const results = await data.searchPerson(this.searchName);
|
||||
const results = await searchPerson(this.searchName);
|
||||
// Exclude people already in the list
|
||||
const idSet = new Set(this.people.map(p => p.id));
|
||||
this.searchResults = results.filter(p => !idSet.has(p.id));
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
<script>
|
||||
import { getMyShoppingList, saveMyShoppingList } from '@/api/shopping'
|
||||
import { useAuth } from '@/composables/useAuth'
|
||||
|
||||
import EditableIngredientsPanel from '@/components/ingredients/EditableIngredientsPanel.vue'
|
||||
|
||||
|
|
@ -47,7 +48,8 @@ export default {
|
|||
return { ingredients: [], person: null }
|
||||
},
|
||||
async beforeMount() {
|
||||
const person = await this.$router.app?.config?.globalProperties?.$user || null;
|
||||
const { loadUser } = useAuth()
|
||||
const person = await loadUser()
|
||||
if (!person)
|
||||
return this.$router.push({ name: 'login' });
|
||||
|
||||
|
|
|
|||
22
src/composables/useAuth.js
Normal file
22
src/composables/useAuth.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import { ref } from 'vue'
|
||||
import { currentUser as apiCurrentUser, login as apiLogin } from '@/api/auth'
|
||||
|
||||
const user = ref(null)
|
||||
let initialized = false
|
||||
|
||||
export async function loadUser() {
|
||||
if (!initialized) {
|
||||
user.value = await apiCurrentUser()
|
||||
initialized = true
|
||||
}
|
||||
return user.value
|
||||
}
|
||||
|
||||
export async function login(username) {
|
||||
user.value = await apiLogin(username)
|
||||
return user.value
|
||||
}
|
||||
|
||||
export function useAuth() {
|
||||
return { user, loadUser, login }
|
||||
}
|
||||
Loading…
Reference in a new issue