---
task: ManageStoresAdmin page — show Delete and Assign Products actions for STORE_OWNER account type on stores they own
cycles: 5
context: true
private: false
started: 2026-05-17T08:00:00Z
finished: 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):**
```js
const { isUltimate, isSuperOperator, isOperator, user } = useAuth()
// missing: isStoreOwner
```

**canModifyStore function (lines 25-27):**
```js
const canModifyStore = (store) => {
    return !!store.user_can_manage
}
```

**Action buttons (lines 242-254):**
```vue
<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):**
```php
->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`:
```php
$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):
```php
->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
