Files
BarangaySystem/.claude/plans/9407eb3f723064594aef12202c29e320-complete.md
2026-06-06 18:43:00 +08:00

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 imports isUltimate, isSuperOperator, isOperator from useAuth; does not import isStoreOwner
  • app/Http/Controllers/Market/StoreController.php [lines 1299-1350] — listStores_Admin: for non-Big3 users sets $s->user_can_manage as dynamic attribute via ->each(); dynamic Eloquent attributes may not serialize reliably in Hypervel
  • resources/js/composables/Core/useAuth.js [lines 106, 118-141] — exports isStoreOwner computed (role === STORE_OWNER); already available but not used in ManageStoresAdmin

steps

  1. In ManageStoresAdmin.vue line 16, add isStoreOwner to destructured useAuth() return
  2. In ManageStoresAdmin.vue, update canModifyStore to also return true when isStoreOwner.value AND store.user_can_manage is truthy — or add a separate isOwnerOf(store) helper that checks isStoreOwner.value && !!store.user_can_manage as secondary gate on the action buttons
  3. In ManageStoresAdmin.vue action buttons column (lines 247-254), change the v-if on Delete and Assign Products buttons to: v-if="canModifyStore(store) || isStoreOwner" is NOT correct (too broad); instead ensure canModifyStore works by fixing step 4 below
  4. In StoreController.php listStores_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 $attributes array and is included in the JSON response
  5. Verify listStores_Admin correctly includes store owner stores: $allowedUserIds = [$user->id, ...$user->getAllDescendants()]owner_id of 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-check or tsc --noEmit if available)
  • constraints: Do not change route access control — store owners already have access to /Admin/Stores/List, /Admin/Store/Delete, /Admin/Store/ToggleStatus routes (middleware is only module:stores, not role-gated)
  • The deleteStore and assignProducts functions in ManageStoresAdmin already handle the STORE_OWNER case correctly via canModifyStore guard — no logic change needed there
  • MyStores.vue (at /my-stores) is a separate page not linked from HomeStoreOwner; ignore it for this task