feat(tenancy): add delete button on table + add-to-store in edit modal
All checks were successful
CI / ruff (push) Successful in 13s
CI / pytest (push) Successful in 2h33m59s
CI / validate (push) Successful in 31s
CI / dependency-scanning (push) Successful in 35s
CI / docs (push) Successful in 49s
CI / deploy (push) Successful in 1m13s

Table actions now show view + edit + delete (trash icon) for non-owner
members. Delete opens the existing remove-from-all-stores modal.

Edit modal enhanced with "Add to another store" section:
- Shows a dashed-border card with store dropdown + role dropdown + add button
- Only appears when the member is not yet in all merchant stores
- Uses the existing invite API to add the member to the selected store

i18n: 2 new keys (add_to_store, select_store) in 4 locales.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 21:36:42 +02:00
parent 50d50fcbd0
commit a247622d23
6 changed files with 94 additions and 5 deletions

View File

@@ -38,6 +38,12 @@ function merchantTeam() {
showViewModal: false,
selectedMember: null,
// Add to store form (inside edit modal)
addStoreForm: {
store_id: '',
role_name: 'staff',
},
// Invite form
inviteForm: {
email: '',
@@ -186,6 +192,45 @@ function merchantTeam() {
this.showInviteModal = true;
},
/**
* Get stores the member is NOT yet in (for "Add to store" in edit modal)
*/
getAvailableStores(member) {
if (!member || !member.stores) return this.stores;
const memberStoreIds = member.stores.map(s => s.store_id);
return this.stores.filter(s => !memberStoreIds.includes(s.id));
},
/**
* Add member to another store (invites them via existing invite API)
*/
async addMemberToStore(member) {
if (!this.addStoreForm.store_id) return;
this.saving = true;
try {
await apiClient.post('/merchants/account/team/invite', {
email: member.email,
store_ids: [parseInt(this.addStoreForm.store_id)],
role_name: this.addStoreForm.role_name,
});
Utils.showToast(I18n.t('tenancy.messages.invitation_sent_successfully'), 'success');
merchantTeamLog.info('Added member to store:', this.addStoreForm.store_id);
this.addStoreForm.store_id = '';
this.addStoreForm.role_name = 'staff';
this.showEditModal = false;
this.selectedMember = null;
await this.loadTeamData();
} catch (error) {
merchantTeamLog.error('Failed to add member to store:', error);
Utils.showToast(error.message || 'Failed to add member to store', 'error');
} finally {
this.saving = false;
}
},
/**
* Toggle store in invite form store_ids
*/
@@ -242,6 +287,7 @@ function merchantTeam() {
*/
openEditModal(member) {
this.selectedMember = JSON.parse(JSON.stringify(member));
this.addStoreForm = { store_id: '', role_name: 'staff' };
this.showEditModal = true;
},