Enables equity eligibility for users

Allows superusers to grant and revoke equity eligibility for users.
Adds UI components for managing equity eligibility.
Equity-eligible users can then contribute expenses as equity.
This commit is contained in:
padreug 2025-11-08 10:14:24 +01:00
parent 33c294de7f
commit eefabc3441
4 changed files with 338 additions and 1 deletions

View file

@ -723,6 +723,7 @@
></q-select>
<q-select
v-if="userInfo && userInfo.is_equity_eligible"
filled
dense
v-model="expenseDialog.isEquity"
@ -735,8 +736,25 @@
emit-value
map-options
label="Type *"
hint="Choose whether this is a liability (Castle owes you) or an equity contribution"
></q-select>
<!-- If user is not equity eligible, force liability -->
<div v-else>
<q-input
filled
dense
readonly
:model-value="'Liability (Castle owes me)'"
label="Type"
hint="This expense will be recorded as a liability (Castle owes you)"
>
<template v-slot:prepend>
<q-icon name="info" color="blue-grey-7"></q-icon>
</template>
</q-input>
</div>
<q-input
filled
dense

View file

@ -44,6 +44,7 @@
<q-tabs v-model="activeTab" class="text-primary" dense>
<q-tab name="by-user" icon="people" label="By User"></q-tab>
<q-tab name="by-account" icon="account_balance" label="By Account"></q-tab>
<q-tab name="equity" icon="account_balance_wallet" label="Equity Eligibility"></q-tab>
</q-tabs>
<q-separator></q-separator>
@ -170,6 +171,68 @@
</q-card>
</div>
</q-tab-panel>
<!-- Equity Eligibility View -->
<q-tab-panel name="equity">
<div v-if="loading" class="row justify-center q-pa-md">
<q-spinner color="primary" size="3em"></q-spinner>
</div>
<div class="row q-mb-md">
<div class="col">
<q-btn
color="primary"
icon="add"
label="Grant Equity Eligibility"
@click="showGrantEquityDialog = true"
:disable="!isSuperUser"
>
<q-tooltip v-if="!isSuperUser">Admin access required</q-tooltip>
</q-btn>
</div>
</div>
<div v-if="equityEligibleUsers.length === 0" class="text-center q-pa-md">
<q-icon name="info" size="3em" color="grey-5"></q-icon>
<p class="text-grey-6">No equity-eligible users yet</p>
</div>
<div v-else class="q-gutter-md">
<q-card v-for="equity in equityEligibleUsers" :key="equity.user_id" flat bordered>
<q-card-section>
<div class="row items-center">
<div class="col">
<div class="text-h6">
<q-icon name="person" class="q-mr-sm"></q-icon>
{% raw %}{{ equity.user_id }}{% endraw %}
</div>
<div class="text-caption text-grey-7 q-mt-sm">
<strong>Equity Account:</strong> {% raw %}{{ equity.equity_account_name }}{% endraw %}
</div>
<div v-if="equity.notes" class="text-caption text-grey-7 q-mt-xs">
<strong>Notes:</strong> {% raw %}{{ equity.notes }}{% endraw %}
</div>
<div class="text-caption text-grey-6 q-mt-xs">
Granted: {% raw %}{{ formatDate(equity.granted_at) }}{% endraw %}
</div>
</div>
<div class="col-auto">
<q-btn
flat
round
dense
icon="delete"
color="negative"
@click="confirmRevokeEquity(equity)"
>
<q-tooltip>Revoke Equity Eligibility</q-tooltip>
</q-btn>
</div>
</div>
</q-card-section>
</q-card>
</div>
</q-tab-panel>
</q-tab-panels>
</q-card-section>
</q-card>
@ -348,4 +411,116 @@
</q-card-actions>
</q-card>
</q-dialog>
<!-- Grant Equity Eligibility Dialog -->
<q-dialog v-model="showGrantEquityDialog" position="top">
<q-card class="q-pa-lg" style="min-width: 500px">
<q-card-section>
<div class="text-h6">Grant Equity Eligibility</div>
<div class="text-caption text-grey-7">
Grant a user the ability to contribute expenses as equity instead of liability.
An equity account will be automatically created for this user.
</div>
</q-card-section>
<q-card-section class="q-gutter-md">
<!-- User -->
<q-select
v-model="grantEquityForm.user_id"
label="User *"
hint="Search and select a user"
:options="userOptions"
option-value="id"
option-label="label"
emit-value
map-options
use-input
@filter="filterUsers"
outlined
dense
:rules="[val => !!val || 'User is required']"
>
<template v-slot:prepend>
<q-icon name="person"></q-icon>
</template>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
No users found
</q-item-section>
</q-item>
</template>
</q-select>
<!-- Notes (Optional) -->
<q-input
v-model="grantEquityForm.notes"
label="Notes (Optional)"
hint="Optional notes for admin reference"
type="textarea"
outlined
dense
rows="3"
>
<template v-slot:prepend>
<q-icon name="note"></q-icon>
</template>
</q-input>
</q-card-section>
<q-card-actions align="right">
<q-btn flat label="Cancel" color="grey" v-close-popup></q-btn>
<q-btn
unelevated
label="Grant Equity Eligibility"
color="primary"
@click="grantEquityEligibility"
:loading="grantingEquity"
:disable="!grantEquityForm.user_id"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<!-- Revoke Equity Confirmation Dialog -->
<q-dialog v-model="showRevokeEquityDialog" persistent>
<q-card>
<q-card-section>
<div class="text-h6">Revoke Equity Eligibility?</div>
</q-card-section>
<q-card-section v-if="equityToRevoke">
<p>Are you sure you want to revoke equity eligibility for this user?</p>
<p class="text-caption text-grey-7">
<strong>Note:</strong> This will prevent them from adding new expenses as equity contributions.
Their existing equity account and contributions will remain unchanged.
</p>
<q-list dense bordered class="rounded-borders q-mt-md">
<q-item>
<q-item-section>
<q-item-label caption>User</q-item-label>
<q-item-label>{% raw %}{{ equityToRevoke.user_id }}{% endraw %}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label caption>Equity Account</q-item-label>
<q-item-label>{% raw %}{{ equityToRevoke.equity_account_name }}{% endraw %}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-card-section>
<q-card-actions align="right">
<q-btn flat label="Cancel" color="grey" v-close-popup></q-btn>
<q-btn
unelevated
label="Revoke"
color="negative"
@click="revokeEquityEligibility"
:loading="revokingEquity"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
{% endblock %}