4.3 KiB
4.3 KiB
task, cycles, context, private, started, finished
| task | cycles | context | private | started | finished |
|---|---|---|---|---|---|
| ManageStoresAdmin page — show Delete and Assign Products actions for STORE_OWNER account type on stores they own | 5 | true | false | 2026-05-17T08:00:00Z | 2026-05-17T08:01:30Z |
files
- resources/js/Pages/ManageStoresAdmin.vue [lines 1-28, 88-125, 127-148, 242-263] — main page; action buttons gated by
canModifyStore(store)→!!store.user_can_manage; currently only importsisUltimate, isSuperOperator, isOperatorfrom useAuth; does not importisStoreOwner - app/Http/Controllers/Market/StoreController.php [lines 1299-1350] —
listStores_Admin: for non-Big3 users sets$s->user_can_manageas dynamic attribute via->each(); dynamic Eloquent attributes may not serialize reliably in Hypervel - resources/js/composables/Core/useAuth.js [lines 106, 118-141] — exports
isStoreOwnercomputed (role === STORE_OWNER); already available but not used in ManageStoresAdmin
steps
- In
ManageStoresAdmin.vueline 16, addisStoreOwnerto destructureduseAuth()return - In
ManageStoresAdmin.vue, updatecanModifyStoreto also return true whenisStoreOwner.valueANDstore.user_can_manageis truthy — or add a separateisOwnerOf(store)helper that checksisStoreOwner.value && !!store.user_can_manageas secondary gate on the action buttons - In
ManageStoresAdmin.vueaction buttons column (lines 247-254), change thev-ifon Delete and Assign Products buttons to:v-if="canModifyStore(store) || isStoreOwner"is NOT correct (too broad); instead ensurecanModifyStoreworks by fixing step 4 below - In
StoreController.phplistStores_Admin(around line 1317 and 1333), replace dynamic attribute assignment$s->user_can_manage = ...with$s->setAttribute('user_can_manage', ...)to guarantee it lands in the model's$attributesarray and is included in the JSON response - Verify
listStores_Admincorrectly includes store owner stores:$allowedUserIds = [$user->id, ...$user->getAllDescendants()]—owner_idof the store must be in this list for store owners who created stores; no change needed if logic is already correct
context
ManageStoresAdmin.vue — useAuth import (line 16):
const { isUltimate, isSuperOperator, isOperator, user } = useAuth()
// missing: isStoreOwner
canModifyStore function (lines 25-27):
const canModifyStore = (store) => {
return !!store.user_can_manage
}
Action buttons (lines 242-254):
<div class="d-flex justify-content-end gap-2">
<button @click="viewStore(store)" ...> <!-- no v-if, always shows -->
<button v-if="canModifyStore(store)" @click="navigate({page:'AddProductsToStore',...})"> <!-- Assign Products -->
<button v-if="canModifyStore(store)" @click="editStore(store)"> <!-- Edit -->
<button v-if="canModifyStore(store)" @click="deleteStore(store)"> <!-- Delete -->
</div>
Backend listStores_Admin — non-Big3 path (StoreController.php ~1333):
->each(function ($s) use ($allowedUserIds) {
$s->user_can_manage = in_array($s->owner_id, $allowedUserIds) // dynamic property — may not serialize
|| in_array($s->manager_id, $allowedUserIds)
|| $s->managers->pluck('user_id')->intersect($allowedUserIds)->isNotEmpty();
unset($s->managers);
});
Fix: use setAttribute:
$s->setAttribute('user_can_manage',
in_array($s->owner_id, $allowedUserIds)
|| in_array($s->manager_id, $allowedUserIds)
|| $s->managers->pluck('user_id')->intersect($allowedUserIds)->isNotEmpty()
);
Also fix the Big3 path (~line 1317):
->each(fn($s) => $s->user_can_manage = true);
// change to:
->each(fn($s) => $s->setAttribute('user_can_manage', true));
notes
- dictionary: none
- linters: eslint, tsc (check with
npm run type-checkortsc --noEmitif available) - constraints: Do not change route access control — store owners already have access to
/Admin/Stores/List,/Admin/Store/Delete,/Admin/Store/ToggleStatusroutes (middleware is onlymodule:stores, not role-gated) - The
deleteStoreandassignProductsfunctions in ManageStoresAdmin already handle the STORE_OWNER case correctly viacanModifyStoreguard — no logic change needed there MyStores.vue(at/my-stores) is a separate page not linked from HomeStoreOwner; ignore it for this task