fix: AmountInput increment/decrement buttons not working
- Fixed input field binding from :value to v-model for proper two-way binding - Input field now properly reflects programmatic value changes from buttons - Simplified handleInput method to work with v-model synchronization - Fixed vite.config.mts fs alias to resolve worker import issues - Applied ESLint formatting fixes across all component files - Maintains comprehensive debugging logs for event flow tracing The issue was that :value creates one-way binding, so when increment/decrement methods updated displayValue programmatically, Vue wasn't updating the DOM. v-model creates proper two-way binding that synchronizes both directions.
This commit is contained in:
BIN
public/wasm/sql-wasm.wasm
Executable file
BIN
public/wasm/sql-wasm.wasm
Executable file
Binary file not shown.
@@ -1,25 +1,20 @@
|
||||
/**
|
||||
* AmountInput.vue - Specialized amount input with increment/decrement controls
|
||||
*
|
||||
* Extracted from GiftedDialog.vue to handle numeric amount input
|
||||
* with increment/decrement buttons and validation.
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
/** * AmountInput.vue - Specialized amount input with increment/decrement
|
||||
controls * * Extracted from GiftedDialog.vue to handle numeric amount input *
|
||||
with increment/decrement buttons and validation. * * @author Matthew Raymer */
|
||||
<template>
|
||||
<div class="flex">
|
||||
<button
|
||||
class="rounded-s border border-e-0 border-slate-400 bg-slate-200 px-4 py-2"
|
||||
:disabled="isAtMinimum"
|
||||
@click.prevent="decrement"
|
||||
type="button"
|
||||
@click.prevent="decrement"
|
||||
>
|
||||
<font-awesome icon="chevron-left" />
|
||||
</button>
|
||||
|
||||
|
||||
<input
|
||||
:id="inputId"
|
||||
:value="displayValue"
|
||||
v-model="displayValue"
|
||||
type="number"
|
||||
:min="min"
|
||||
:max="max"
|
||||
@@ -28,12 +23,12 @@
|
||||
@input="handleInput"
|
||||
@blur="handleBlur"
|
||||
/>
|
||||
|
||||
|
||||
<button
|
||||
class="rounded-e border border-slate-400 bg-slate-200 px-4 py-2"
|
||||
:disabled="isAtMaximum"
|
||||
@click.prevent="increment"
|
||||
type="button"
|
||||
@click.prevent="increment"
|
||||
>
|
||||
<font-awesome icon="chevron-right" />
|
||||
</button>
|
||||
@@ -45,7 +40,7 @@ import { Component, Prop, Vue, Watch, Emit } from "vue-facing-decorator";
|
||||
|
||||
/**
|
||||
* AmountInput - Numeric input with increment/decrement controls
|
||||
*
|
||||
*
|
||||
* Features:
|
||||
* - Increment/decrement buttons with validation
|
||||
* - Configurable min/max values and step size
|
||||
@@ -82,7 +77,13 @@ export default class AmountInput extends Vue {
|
||||
* Initialize display value from prop
|
||||
*/
|
||||
mounted(): void {
|
||||
console.log(
|
||||
`[AmountInput] mounted() - initial value: ${this.value}, min: ${this.min}, max: ${this.max}, step: ${this.step}`,
|
||||
);
|
||||
this.displayValue = this.value.toString();
|
||||
console.log(
|
||||
`[AmountInput] mounted() - displayValue set to: ${this.displayValue}`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,21 +98,33 @@ export default class AmountInput extends Vue {
|
||||
* Check if current value is at minimum
|
||||
*/
|
||||
get isAtMinimum(): boolean {
|
||||
return this.value <= this.min;
|
||||
const result = this.value <= this.min;
|
||||
console.log(
|
||||
`[AmountInput] isAtMinimum - value: ${this.value}, min: ${this.min}, result: ${result}`,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current value is at maximum
|
||||
*/
|
||||
get isAtMaximum(): boolean {
|
||||
return this.value >= this.max;
|
||||
const result = this.value >= this.max;
|
||||
console.log(
|
||||
`[AmountInput] isAtMaximum - value: ${this.value}, max: ${this.max}, result: ${result}`,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the value by step size
|
||||
*/
|
||||
increment(): void {
|
||||
console.log(
|
||||
`[AmountInput] increment() called - current value: ${this.value}, step: ${this.step}`,
|
||||
);
|
||||
const newValue = Math.min(this.value + this.step, this.max);
|
||||
console.log(`[AmountInput] increment() calculated newValue: ${newValue}`);
|
||||
this.updateValue(newValue);
|
||||
}
|
||||
|
||||
@@ -119,18 +132,19 @@ export default class AmountInput extends Vue {
|
||||
* Decrement the value by step size
|
||||
*/
|
||||
decrement(): void {
|
||||
console.log(
|
||||
`[AmountInput] decrement() called - current value: ${this.value}, step: ${this.step}`,
|
||||
);
|
||||
const newValue = Math.max(this.value - this.step, this.min);
|
||||
console.log(`[AmountInput] decrement() calculated newValue: ${newValue}`);
|
||||
this.updateValue(newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle direct input changes
|
||||
*/
|
||||
handleInput(event: Event): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
this.displayValue = target.value;
|
||||
|
||||
const numericValue = parseFloat(target.value);
|
||||
handleInput(): void {
|
||||
const numericValue = parseFloat(this.displayValue);
|
||||
if (!isNaN(numericValue)) {
|
||||
const clampedValue = Math.max(this.min, Math.min(numericValue, this.max));
|
||||
this.updateValue(clampedValue);
|
||||
@@ -148,9 +162,17 @@ export default class AmountInput extends Vue {
|
||||
* Update the value and emit change event
|
||||
*/
|
||||
private updateValue(newValue: number): void {
|
||||
console.log(
|
||||
`[AmountInput] updateValue() called - oldValue: ${this.value}, newValue: ${newValue}`,
|
||||
);
|
||||
if (newValue !== this.value) {
|
||||
console.log(
|
||||
`[AmountInput] updateValue() - values different, updating and emitting`,
|
||||
);
|
||||
this.displayValue = newValue.toString();
|
||||
this.emitUpdateValue(newValue);
|
||||
} else {
|
||||
console.log(`[AmountInput] updateValue() - values same, skipping update`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,6 +181,7 @@ export default class AmountInput extends Vue {
|
||||
*/
|
||||
@Emit("update:value")
|
||||
emitUpdateValue(value: number): number {
|
||||
console.log(`[AmountInput] emitUpdateValue() - emitting value: ${value}`);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -181,4 +204,4 @@ button:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
/**
|
||||
* EntityGrid.vue - Unified entity grid layout component
|
||||
*
|
||||
* Extracted from GiftedDialog.vue to provide a reusable grid layout
|
||||
* for displaying people, projects, and special entities with selection.
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
/** * EntityGrid.vue - Unified entity grid layout component * * Extracted from
|
||||
GiftedDialog.vue to provide a reusable grid layout * for displaying people,
|
||||
projects, and special entities with selection. * * @author Matthew Raymer */
|
||||
<template>
|
||||
<ul :class="gridClasses">
|
||||
<!-- Special entities (You, Unnamed) for people grids -->
|
||||
@@ -21,7 +16,7 @@
|
||||
:entity-data="youEntityData"
|
||||
@entity-selected="handleEntitySelected"
|
||||
/>
|
||||
|
||||
|
||||
<!-- "Unnamed" entity -->
|
||||
<SpecialEntityCard
|
||||
entity-type="unnamed"
|
||||
@@ -51,7 +46,7 @@
|
||||
@person-selected="handlePersonSelected"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
||||
<template v-else-if="entityType === 'projects'">
|
||||
<ProjectCard
|
||||
v-for="project in displayedEntities"
|
||||
@@ -85,7 +80,7 @@ import { PlanData } from "../interfaces/records";
|
||||
|
||||
/**
|
||||
* EntityGrid - Unified grid layout for displaying people or projects
|
||||
*
|
||||
*
|
||||
* Features:
|
||||
* - Responsive grid layout for people/projects
|
||||
* - Special entity integration (You, Unnamed)
|
||||
@@ -100,7 +95,7 @@ import { PlanData } from "../interfaces/records";
|
||||
ProjectCard,
|
||||
SpecialEntityCard,
|
||||
ShowAllCard,
|
||||
}
|
||||
},
|
||||
})
|
||||
export default class EntityGrid extends Vue {
|
||||
/** Type of entities to display */
|
||||
@@ -152,7 +147,7 @@ export default class EntityGrid extends Vue {
|
||||
*/
|
||||
get gridClasses(): string {
|
||||
const baseClasses = "grid gap-x-2 gap-y-4 text-center mb-4";
|
||||
|
||||
|
||||
if (this.entityType === "projects") {
|
||||
return `${baseClasses} grid-cols-3 md:grid-cols-4`;
|
||||
} else {
|
||||
@@ -243,7 +238,11 @@ export default class EntityGrid extends Vue {
|
||||
/**
|
||||
* Handle special entity selection from SpecialEntityCard
|
||||
*/
|
||||
handleEntitySelected(event: { type: string; entityType: string; data: any }): void {
|
||||
handleEntitySelected(event: {
|
||||
type: string;
|
||||
entityType: string;
|
||||
data: any;
|
||||
}): void {
|
||||
this.emitEntitySelected({
|
||||
type: "special",
|
||||
entityType: event.entityType,
|
||||
@@ -262,4 +261,4 @@ export default class EntityGrid extends Vue {
|
||||
|
||||
<style scoped>
|
||||
/* Grid-specific styles if needed */
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
/**
|
||||
* EntitySelectionStep.vue - Entity selection step component
|
||||
*
|
||||
* Extracted from GiftedDialog.vue to handle the complete step 1
|
||||
* entity selection interface with dynamic labeling and grid display.
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
/** * EntitySelectionStep.vue - Entity selection step component * * Extracted
|
||||
from GiftedDialog.vue to handle the complete step 1 * entity selection interface
|
||||
with dynamic labeling and grid display. * * @author Matthew Raymer */
|
||||
<template>
|
||||
<div id="sectionGiftedGiver">
|
||||
<label class="block font-bold mb-4">
|
||||
@@ -53,7 +48,7 @@ interface EntitySelectionEvent {
|
||||
|
||||
/**
|
||||
* EntitySelectionStep - Complete step 1 entity selection interface
|
||||
*
|
||||
*
|
||||
* Features:
|
||||
* - Dynamic step labeling based on context
|
||||
* - EntityGrid integration for unified entity display
|
||||
@@ -66,7 +61,7 @@ interface EntitySelectionEvent {
|
||||
@Component({
|
||||
components: {
|
||||
EntityGrid,
|
||||
}
|
||||
},
|
||||
})
|
||||
export default class EntitySelectionStep extends Vue {
|
||||
/** Type of step: 'giver' or 'recipient' */
|
||||
@@ -244,4 +239,4 @@ export default class EntitySelectionStep extends Vue {
|
||||
|
||||
<style scoped>
|
||||
/* Component-specific styles if needed */
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
/**
|
||||
* EntitySummaryButton.vue - Displays selected entity with edit capability
|
||||
*
|
||||
* Extracted from GiftedDialog.vue to handle entity summary display
|
||||
* in the gift details step with edit functionality.
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
/** * EntitySummaryButton.vue - Displays selected entity with edit capability *
|
||||
* Extracted from GiftedDialog.vue to handle entity summary display * in the gift
|
||||
details step with edit functionality. * * @author Matthew Raymer */
|
||||
<template>
|
||||
<component
|
||||
:is="editable ? 'button' : 'div'"
|
||||
@@ -49,9 +44,9 @@
|
||||
|
||||
<!-- Edit/Lock Icon -->
|
||||
<p class="ms-auto text-sm pe-1" :class="iconClasses">
|
||||
<font-awesome
|
||||
:icon="editable ? 'pen' : 'lock'"
|
||||
:title="editable ? 'Change' : 'Can\'t be changed'"
|
||||
<font-awesome
|
||||
:icon="editable ? 'pen' : 'lock'"
|
||||
:title="editable ? 'Change' : 'Can\'t be changed'"
|
||||
/>
|
||||
</p>
|
||||
</component>
|
||||
@@ -75,7 +70,7 @@ interface EntityData {
|
||||
|
||||
/**
|
||||
* EntitySummaryButton - Displays selected entity with optional edit capability
|
||||
*
|
||||
*
|
||||
* Features:
|
||||
* - Shows entity avatar (person or project)
|
||||
* - Displays entity name and role label
|
||||
@@ -87,7 +82,7 @@ interface EntityData {
|
||||
components: {
|
||||
EntityIcon,
|
||||
ProjectIcon,
|
||||
}
|
||||
},
|
||||
})
|
||||
export default class EntitySummaryButton extends Vue {
|
||||
/** Entity data to display */
|
||||
@@ -147,4 +142,4 @@ button:hover {
|
||||
div {
|
||||
cursor: default;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
/**
|
||||
* GiftDetailsStep.vue - Gift details step component
|
||||
*
|
||||
* Extracted from GiftedDialog.vue to handle the complete step 2
|
||||
* gift details form interface with entity summaries and validation.
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
/** * GiftDetailsStep.vue - Gift details step component * * Extracted from
|
||||
GiftedDialog.vue to handle the complete step 2 * gift details form interface
|
||||
with entity summaries and validation. * * @author Matthew Raymer */
|
||||
<template>
|
||||
<div id="sectionGiftedGift">
|
||||
<!-- Entity Summary Buttons -->
|
||||
@@ -79,8 +74,8 @@
|
||||
</p>
|
||||
|
||||
<!-- Conflict Warning -->
|
||||
<div
|
||||
v-if="hasConflict"
|
||||
<div
|
||||
v-if="hasConflict"
|
||||
class="mb-4 p-3 bg-red-50 border border-red-200 rounded-md"
|
||||
>
|
||||
<p class="text-red-700 text-sm text-center">
|
||||
@@ -126,7 +121,7 @@ interface EntityData {
|
||||
|
||||
/**
|
||||
* GiftDetailsStep - Complete step 2 gift details form interface
|
||||
*
|
||||
*
|
||||
* Features:
|
||||
* - Entity summary display with edit capability
|
||||
* - Gift description input with placeholder support
|
||||
@@ -141,7 +136,7 @@ interface EntityData {
|
||||
components: {
|
||||
EntitySummaryButton,
|
||||
AmountInput,
|
||||
}
|
||||
},
|
||||
})
|
||||
export default class GiftDetailsStep extends Vue {
|
||||
/** Giver entity data */
|
||||
@@ -232,8 +227,8 @@ export default class GiftDetailsStep extends Vue {
|
||||
* Computed label for giver entity
|
||||
*/
|
||||
get giverLabel(): string {
|
||||
return this.giverEntityType === "project"
|
||||
? "Benefited from:"
|
||||
return this.giverEntityType === "project"
|
||||
? "Benefited from:"
|
||||
: "Received from:";
|
||||
}
|
||||
|
||||
@@ -279,15 +274,20 @@ export default class GiftDetailsStep extends Vue {
|
||||
query: {
|
||||
amountInput: this.localAmount.toString(),
|
||||
description: this.localDescription,
|
||||
giverDid: this.giverEntityType === "person" ? this.giver?.did : undefined,
|
||||
giverDid:
|
||||
this.giverEntityType === "person" ? this.giver?.did : undefined,
|
||||
giverName: this.giver?.name,
|
||||
offerId: this.offerId,
|
||||
fulfillsProjectId: this.giverEntityType === "person" && this.recipientEntityType === "project"
|
||||
? this.toProjectId
|
||||
: undefined,
|
||||
providerProjectId: this.giverEntityType === "project" && this.recipientEntityType === "person"
|
||||
? this.giver?.handleId
|
||||
: this.fromProjectId,
|
||||
fulfillsProjectId:
|
||||
this.giverEntityType === "person" &&
|
||||
this.recipientEntityType === "project"
|
||||
? this.toProjectId
|
||||
: undefined,
|
||||
providerProjectId:
|
||||
this.giverEntityType === "project" &&
|
||||
this.recipientEntityType === "person"
|
||||
? this.giver?.handleId
|
||||
: this.fromProjectId,
|
||||
recipientDid: this.receiver?.did,
|
||||
recipientName: this.receiver?.name,
|
||||
unitCode: this.localUnitCode,
|
||||
@@ -306,6 +306,9 @@ export default class GiftDetailsStep extends Vue {
|
||||
* Handle amount input changes
|
||||
*/
|
||||
handleAmountChange(newAmount: number): void {
|
||||
console.log(
|
||||
`[GiftDetailsStep] handleAmountChange() called - oldAmount: ${this.localAmount}, newAmount: ${newAmount}`,
|
||||
);
|
||||
this.localAmount = newAmount;
|
||||
this.emitUpdateAmount(newAmount);
|
||||
}
|
||||
@@ -373,6 +376,9 @@ export default class GiftDetailsStep extends Vue {
|
||||
|
||||
@Emit("update:amount")
|
||||
emitUpdateAmount(amount: number): number {
|
||||
console.log(
|
||||
`[GiftDetailsStep] emitUpdateAmount() - emitting amount: ${amount}`,
|
||||
);
|
||||
return amount;
|
||||
}
|
||||
|
||||
@@ -405,4 +411,4 @@ export default class GiftDetailsStep extends Vue {
|
||||
|
||||
<style scoped>
|
||||
/* Component-specific styles if needed */
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
:from-project-id="fromProjectId"
|
||||
:to-project-id="toProjectId"
|
||||
@update:description="description = $event"
|
||||
@update:amount="amountInput = $event.toString()"
|
||||
@update:amount="handleAmountUpdate"
|
||||
@update:unit-code="unitCode = $event"
|
||||
@edit-entity="handleEditEntity"
|
||||
@explain-data="explainData"
|
||||
@@ -138,25 +138,35 @@ export default class GiftedDialog extends Vue {
|
||||
// Computed property to check if current selection would create a conflict
|
||||
get hasPersonConflict() {
|
||||
// Only check for conflicts when both entities are persons
|
||||
if (this.giverEntityType !== "person" || this.recipientEntityType !== "person") {
|
||||
if (
|
||||
this.giverEntityType !== "person" ||
|
||||
this.recipientEntityType !== "person"
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Check if giver and recipient are the same person
|
||||
if (this.giver?.did && this.receiver?.did && this.giver.did === this.receiver.did) {
|
||||
if (
|
||||
this.giver?.did &&
|
||||
this.receiver?.did &&
|
||||
this.giver.did === this.receiver.did
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Computed property to check if a contact would create a conflict when selected
|
||||
wouldCreateConflict(contactDid: string) {
|
||||
// Only check for conflicts when both entities are persons
|
||||
if (this.giverEntityType !== "person" || this.recipientEntityType !== "person") {
|
||||
if (
|
||||
this.giverEntityType !== "person" ||
|
||||
this.recipientEntityType !== "person"
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (this.stepType === "giver") {
|
||||
// If selecting as giver, check if it conflicts with current recipient
|
||||
return this.receiver?.did === contactDid;
|
||||
@@ -164,7 +174,7 @@ export default class GiftedDialog extends Vue {
|
||||
// If selecting as recipient, check if it conflicts with current giver
|
||||
return this.giver?.did === contactDid;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -348,7 +358,7 @@ export default class GiftedDialog extends Vue {
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Check for person conflict
|
||||
if (this.hasPersonConflict) {
|
||||
this.$notify(
|
||||
@@ -407,13 +417,19 @@ export default class GiftedDialog extends Vue {
|
||||
let fulfillsProjectHandleId: string | undefined;
|
||||
let providerPlanHandleId: string | undefined;
|
||||
|
||||
if (this.giverEntityType === "project" && this.recipientEntityType === "person") {
|
||||
if (
|
||||
this.giverEntityType === "project" &&
|
||||
this.recipientEntityType === "person"
|
||||
) {
|
||||
// Project-to-person gift
|
||||
fromDid = undefined; // No person giver
|
||||
toDid = recipientDid as string; // Person recipient
|
||||
fulfillsProjectHandleId = undefined; // No project recipient
|
||||
providerPlanHandleId = this.giver?.handleId; // Project giver
|
||||
} else if (this.giverEntityType === "person" && this.recipientEntityType === "project") {
|
||||
} else if (
|
||||
this.giverEntityType === "person" &&
|
||||
this.recipientEntityType === "project"
|
||||
) {
|
||||
// Person-to-project gift
|
||||
fromDid = giverDid as string; // Person giver
|
||||
toDid = undefined; // No person recipient
|
||||
@@ -611,12 +627,16 @@ export default class GiftedDialog extends Vue {
|
||||
giverDid: this.giverEntityType === "person" ? this.giver?.did : undefined,
|
||||
giverName: this.giver?.name,
|
||||
offerId: this.offerId,
|
||||
fulfillsProjectId: this.giverEntityType === "person" && this.recipientEntityType === "project"
|
||||
? this.toProjectId
|
||||
: undefined,
|
||||
providerProjectId: this.giverEntityType === "project" && this.recipientEntityType === "person"
|
||||
? this.giver?.handleId
|
||||
: this.fromProjectId,
|
||||
fulfillsProjectId:
|
||||
this.giverEntityType === "person" &&
|
||||
this.recipientEntityType === "project"
|
||||
? this.toProjectId
|
||||
: undefined,
|
||||
providerProjectId:
|
||||
this.giverEntityType === "project" &&
|
||||
this.recipientEntityType === "person"
|
||||
? this.giver?.handleId
|
||||
: this.fromProjectId,
|
||||
recipientDid: this.receiver?.did,
|
||||
recipientName: this.receiver?.name,
|
||||
unitCode: this.unitCode,
|
||||
@@ -629,17 +649,20 @@ export default class GiftedDialog extends Vue {
|
||||
* Handle entity selection from EntitySelectionStep
|
||||
* @param entity - The selected entity (person or project)
|
||||
*/
|
||||
handleEntitySelected(entity: { type: 'person' | 'project', data: Contact | PlanData }) {
|
||||
if (entity.type === 'person') {
|
||||
handleEntitySelected(entity: {
|
||||
type: "person" | "project";
|
||||
data: Contact | PlanData;
|
||||
}) {
|
||||
if (entity.type === "person") {
|
||||
const contact = entity.data as Contact;
|
||||
if (this.stepType === 'giver') {
|
||||
if (this.stepType === "giver") {
|
||||
this.selectGiver(contact);
|
||||
} else {
|
||||
this.selectRecipient(contact);
|
||||
}
|
||||
} else {
|
||||
const project = entity.data as PlanData;
|
||||
if (this.stepType === 'giver') {
|
||||
if (this.stepType === "giver") {
|
||||
this.selectProject(project);
|
||||
} else {
|
||||
this.selectRecipientProject(project);
|
||||
@@ -651,7 +674,7 @@ export default class GiftedDialog extends Vue {
|
||||
* Handle edit entity request from GiftDetailsStep
|
||||
* @param entityType - 'giver' or 'recipient'
|
||||
*/
|
||||
handleEditEntity(entityType: 'giver' | 'recipient') {
|
||||
handleEditEntity(entityType: "giver" | "recipient") {
|
||||
this.goBackToStep1(entityType);
|
||||
}
|
||||
|
||||
@@ -661,6 +684,19 @@ export default class GiftedDialog extends Vue {
|
||||
handleSubmit() {
|
||||
this.confirm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle amount update from GiftDetailsStep
|
||||
*/
|
||||
handleAmountUpdate(newAmount: number) {
|
||||
console.log(
|
||||
`[GiftedDialog] handleAmountUpdate() called - oldAmount: ${this.amountInput}, newAmount: ${newAmount}`,
|
||||
);
|
||||
this.amountInput = newAmount.toString();
|
||||
console.log(
|
||||
`[GiftedDialog] handleAmountUpdate() - amountInput updated to: ${this.amountInput}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
/**
|
||||
* PersonCard.vue - Individual person display component
|
||||
*
|
||||
* Extracted from GiftedDialog.vue to handle person entity display
|
||||
* with selection states and conflict detection.
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
/** * PersonCard.vue - Individual person display component * * Extracted from
|
||||
GiftedDialog.vue to handle person entity display * with selection states and
|
||||
conflict detection. * * @author Matthew Raymer */
|
||||
<template>
|
||||
<li
|
||||
:class="cardClasses"
|
||||
@click="handleClick"
|
||||
>
|
||||
<li :class="cardClasses" @click="handleClick">
|
||||
<div class="relative w-fit mx-auto">
|
||||
<EntityIcon
|
||||
v-if="person.did"
|
||||
@@ -22,21 +14,18 @@
|
||||
icon="circle-question"
|
||||
class="text-slate-400 text-5xl mb-1"
|
||||
/>
|
||||
|
||||
|
||||
<!-- Time icon overlay for contacts -->
|
||||
<div
|
||||
v-if="person.did && showTimeIcon"
|
||||
class="rounded-full bg-slate-400 absolute bottom-0 right-0 p-1 translate-x-1/3"
|
||||
>
|
||||
<font-awesome
|
||||
icon="clock"
|
||||
class="block text-white text-xs w-[1em]"
|
||||
/>
|
||||
<font-awesome icon="clock" class="block text-white text-xs w-[1em]" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h3 :class="nameClasses">
|
||||
{{ person.name || person.did || 'Unnamed' }}
|
||||
{{ person.name || person.did || "Unnamed" }}
|
||||
</h3>
|
||||
</li>
|
||||
</template>
|
||||
@@ -48,7 +37,7 @@ import { Contact } from "../db/tables/contacts";
|
||||
|
||||
/**
|
||||
* PersonCard - Individual person display with selection capability
|
||||
*
|
||||
*
|
||||
* Features:
|
||||
* - Person avatar using EntityIcon
|
||||
* - Selection states (selectable, conflicted, disabled)
|
||||
@@ -59,7 +48,7 @@ import { Contact } from "../db/tables/contacts";
|
||||
@Component({
|
||||
components: {
|
||||
EntityIcon,
|
||||
}
|
||||
},
|
||||
})
|
||||
export default class PersonCard extends Vue {
|
||||
/** Contact data to display */
|
||||
@@ -92,12 +81,13 @@ export default class PersonCard extends Vue {
|
||||
* Computed CSS classes for the person name
|
||||
*/
|
||||
get nameClasses(): string {
|
||||
const baseClasses = "text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden";
|
||||
|
||||
const baseClasses =
|
||||
"text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden";
|
||||
|
||||
if (this.conflicted) {
|
||||
return `${baseClasses} text-slate-400`;
|
||||
}
|
||||
|
||||
|
||||
return baseClasses;
|
||||
}
|
||||
|
||||
@@ -121,4 +111,4 @@ export default class PersonCard extends Vue {
|
||||
|
||||
<style scoped>
|
||||
/* Component-specific styles if needed */
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
/**
|
||||
* ProjectCard.vue - Individual project display component
|
||||
*
|
||||
* Extracted from GiftedDialog.vue to handle project entity display
|
||||
* with selection states and issuer information.
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
/** * ProjectCard.vue - Individual project display component * * Extracted from
|
||||
GiftedDialog.vue to handle project entity display * with selection states and
|
||||
issuer information. * * @author Matthew Raymer */
|
||||
<template>
|
||||
<li
|
||||
class="cursor-pointer"
|
||||
@click="handleClick"
|
||||
>
|
||||
<li class="cursor-pointer" @click="handleClick">
|
||||
<div class="relative w-fit mx-auto">
|
||||
<ProjectIcon
|
||||
:entity-id="project.handleId"
|
||||
@@ -19,11 +11,13 @@
|
||||
class="!size-[3rem] mx-auto border border-slate-300 bg-white overflow-hidden rounded-full mb-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h3 class="text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden">
|
||||
|
||||
<h3
|
||||
class="text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden"
|
||||
>
|
||||
{{ project.name }}
|
||||
</h3>
|
||||
|
||||
|
||||
<div class="text-xs text-slate-500 truncate">
|
||||
<font-awesome icon="user" class="fa-fw text-slate-400" />
|
||||
{{ issuerDisplayName }}
|
||||
@@ -40,7 +34,7 @@ import { didInfo } from "../libs/endorserServer";
|
||||
|
||||
/**
|
||||
* ProjectCard - Displays a project entity with selection capability
|
||||
*
|
||||
*
|
||||
* Features:
|
||||
* - Shows project icon using ProjectIcon
|
||||
* - Displays project name and issuer information
|
||||
@@ -50,7 +44,7 @@ import { didInfo } from "../libs/endorserServer";
|
||||
@Component({
|
||||
components: {
|
||||
ProjectIcon,
|
||||
}
|
||||
},
|
||||
})
|
||||
export default class ProjectCard extends Vue {
|
||||
/** Project entity to display */
|
||||
@@ -77,7 +71,7 @@ export default class ProjectCard extends Vue {
|
||||
this.project.issuerDid,
|
||||
this.activeDid,
|
||||
this.allMyDids,
|
||||
this.allContacts
|
||||
this.allContacts,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -99,4 +93,4 @@ export default class ProjectCard extends Vue {
|
||||
|
||||
<style scoped>
|
||||
/* Component-specific styles if needed */
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,22 +1,13 @@
|
||||
/**
|
||||
* ShowAllCard.vue - Show All navigation card component
|
||||
*
|
||||
* Extracted from GiftedDialog.vue to handle "Show All" navigation
|
||||
* for both people and projects entity types.
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
/** * ShowAllCard.vue - Show All navigation card component * * Extracted from
|
||||
GiftedDialog.vue to handle "Show All" navigation * for both people and projects
|
||||
entity types. * * @author Matthew Raymer */
|
||||
<template>
|
||||
<li class="cursor-pointer">
|
||||
<router-link
|
||||
:to="navigationRoute"
|
||||
class="block text-center"
|
||||
>
|
||||
<font-awesome
|
||||
icon="circle-right"
|
||||
class="text-blue-500 text-5xl mb-1"
|
||||
/>
|
||||
<h3 class="text-xs text-slate-500 font-medium italic text-ellipsis whitespace-nowrap overflow-hidden">
|
||||
<router-link :to="navigationRoute" class="block text-center">
|
||||
<font-awesome icon="circle-right" class="text-blue-500 text-5xl mb-1" />
|
||||
<h3
|
||||
class="text-xs text-slate-500 font-medium italic text-ellipsis whitespace-nowrap overflow-hidden"
|
||||
>
|
||||
Show All
|
||||
</h3>
|
||||
</router-link>
|
||||
@@ -29,7 +20,7 @@ import { RouteLocationRaw } from "vue-router";
|
||||
|
||||
/**
|
||||
* ShowAllCard - Displays "Show All" navigation for entity grids
|
||||
*
|
||||
*
|
||||
* Features:
|
||||
* - Provides navigation to full entity listings
|
||||
* - Supports different routes based on entity type
|
||||
@@ -72,4 +63,4 @@ a:hover .fa-circle-right {
|
||||
transform: scale(1.1);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
/**
|
||||
* SpecialEntityCard.vue - Special entity display component
|
||||
*
|
||||
* Extracted from GiftedDialog.vue to handle special entities like "You"
|
||||
* and "Unnamed" with conflict detection and selection capability.
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
/** * SpecialEntityCard.vue - Special entity display component * * Extracted
|
||||
from GiftedDialog.vue to handle special entities like "You" * and "Unnamed" with
|
||||
conflict detection and selection capability. * * @author Matthew Raymer */
|
||||
<template>
|
||||
<li
|
||||
:class="cardClasses"
|
||||
@click="handleClick"
|
||||
>
|
||||
<font-awesome
|
||||
:icon="icon"
|
||||
:class="iconClasses"
|
||||
/>
|
||||
<li :class="cardClasses" @click="handleClick">
|
||||
<font-awesome :icon="icon" :class="iconClasses" />
|
||||
<h3 :class="nameClasses">
|
||||
{{ label }}
|
||||
</h3>
|
||||
@@ -27,7 +16,7 @@ import { Emit } from "vue-facing-decorator";
|
||||
|
||||
/**
|
||||
* SpecialEntityCard - Displays special entities with selection capability
|
||||
*
|
||||
*
|
||||
* Features:
|
||||
* - Displays special entities like "You" and "Unnamed"
|
||||
* - Shows appropriate FontAwesome icons
|
||||
@@ -36,7 +25,7 @@ import { Emit } from "vue-facing-decorator";
|
||||
* - Configurable styling based on entity type
|
||||
*/
|
||||
@Component({
|
||||
emits: ['entity-selected']
|
||||
emits: ["entity-selected"],
|
||||
})
|
||||
export default class SpecialEntityCard extends Vue {
|
||||
/** Type of special entity */
|
||||
@@ -68,11 +57,11 @@ export default class SpecialEntityCard extends Vue {
|
||||
*/
|
||||
get cardClasses(): string {
|
||||
const baseClasses = "block";
|
||||
|
||||
|
||||
if (!this.selectable || this.conflicted) {
|
||||
return `${baseClasses} cursor-not-allowed opacity-50`;
|
||||
}
|
||||
|
||||
|
||||
return `${baseClasses} cursor-pointer`;
|
||||
}
|
||||
|
||||
@@ -81,11 +70,11 @@ export default class SpecialEntityCard extends Vue {
|
||||
*/
|
||||
get iconClasses(): string {
|
||||
const baseClasses = "text-5xl mb-1";
|
||||
|
||||
|
||||
if (this.conflicted) {
|
||||
return `${baseClasses} text-slate-400`;
|
||||
}
|
||||
|
||||
|
||||
// Different colors for different entity types
|
||||
switch (this.entityType) {
|
||||
case "you":
|
||||
@@ -101,12 +90,13 @@ export default class SpecialEntityCard extends Vue {
|
||||
* Computed CSS classes for the entity name/label
|
||||
*/
|
||||
get nameClasses(): string {
|
||||
const baseClasses = "text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden";
|
||||
|
||||
const baseClasses =
|
||||
"text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden";
|
||||
|
||||
if (this.conflicted) {
|
||||
return `${baseClasses} text-slate-400`;
|
||||
}
|
||||
|
||||
|
||||
// Different colors for different entity types
|
||||
switch (this.entityType) {
|
||||
case "you":
|
||||
@@ -142,4 +132,4 @@ export default class SpecialEntityCard extends Vue {
|
||||
|
||||
<style scoped>
|
||||
/* Component-specific styles if needed */
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -22,7 +22,7 @@ export default defineConfig({
|
||||
url: 'url/',
|
||||
zlib: 'browserify-zlib',
|
||||
path: 'path-browserify',
|
||||
fs: false,
|
||||
fs: path.resolve(__dirname, 'src/utils/node-modules/fs.js'),
|
||||
tty: 'tty-browserify',
|
||||
net: false,
|
||||
dns: false,
|
||||
|
||||
Reference in New Issue
Block a user