Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion app.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
<template>
<NuxtLayout>
<NuxtLayout :key="layoutKey">
<NuxtPage />
</NuxtLayout>
</template>

<script setup>
const route = useRoute();
const layoutKey = computed(() => route.meta.layout || 'default');
</script>

<style lang="scss">
html,
body {
Expand Down
145 changes: 132 additions & 13 deletions assets/scss/_onboarding.scss
Original file line number Diff line number Diff line change
Expand Up @@ -424,34 +424,95 @@
width: 100%;
}

.wallet-options {
.wallet-currency-columns {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;

@media (max-width: $breakpoint-sm) {
grid-template-columns: 1fr;
gap: 1.5rem;
}
}

.wallet-column,
.currency-column {
display: flex;
flex-direction: column;
gap: 0.75rem;
}

.wallet-option {
.column-label {
font-size: 0.9375rem;
font-weight: 600;
color: $text-primary;
margin-bottom: 0.25rem;
}

.wallet-cards {
display: flex;
align-items: center;
flex-direction: column;
gap: 0.5rem;
}

input[type='radio'] {
margin: 0;
.wallet-card {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.625rem 1rem;
border: 2px solid $border-gray;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
background: white;

&:hover {
border-color: $primary;
background: rgba(4, 120, 68, 0.02);
}

label {
font-weight: 500;
color: $text-primary;
cursor: pointer;
&.selected {
border-color: $primary;
background: rgba(4, 120, 68, 0.05);
}
}

.wallet-name-input,
.new-wallet-form {
margin-top: 1rem;
.wallet-radio {
width: 18px;
height: 18px;
accent-color: $primary;
cursor: pointer;
flex-shrink: 0;
}

.wallet-card-content {
display: flex;
flex-direction: column;
gap: 0.75rem;
gap: 0.125rem;
}

.wallet-card-title {
font-weight: 600;
font-size: 0.9375rem;
color: $text-primary;
}

.wallet-card-desc {
font-size: 0.8125rem;
color: $text-muted;
}

.wallet-extra-field,
.currency-section {
display: flex;
flex-direction: column;
gap: 0.5rem;
}

.field-label {
font-size: 0.875rem;
font-weight: 500;
color: $text-secondary;
}

.wallet-input {
Expand All @@ -462,6 +523,7 @@
font-size: 0.875rem;
background: white;
color: $text-primary;
box-sizing: border-box;

&:focus {
outline: none;
Expand All @@ -476,3 +538,60 @@
margin: 0.5rem 0 0 0;
font-style: italic;
}

.categories-setup {
display: flex;
flex-direction: column;
gap: 2rem;
width: 100%;
max-width: 400px;
margin: 0 auto;
}

.categories-card {
padding: 1.5rem;
border: 2px solid $border-gray;
border-radius: 12px;
cursor: pointer;
transition: all 0.2s ease;
background: white;

&:hover {
border-color: $primary;
background: rgba(4, 120, 68, 0.02);
}

&.selected {
border-color: $primary;
background: rgba(4, 120, 68, 0.05);
}
}

.categories-card-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.75rem;
}

.categories-checkbox {
width: 20px;
height: 20px;
accent-color: $primary;
cursor: pointer;
flex-shrink: 0;
}

.categories-card-title {
font-weight: 600;
font-size: 1rem;
color: $text-primary;
}

.categories-card-description {
font-size: 0.875rem;
color: $text-secondary;
line-height: 1.5;
margin: 0;
padding-left: calc(20px + 0.75rem);
}
26 changes: 26 additions & 0 deletions assets/scss/_transaction-form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -483,3 +483,29 @@
}
}
}

.wallet-field-wrapper {
position: relative;
display: flex;
flex-direction: column;
gap: 8px;

.wallet-default-indicator {
position: absolute;
top: 34px;
right: 8px;
display: inline-flex;
align-items: center;
justify-content: center;
background: $primary;
color: white;
font-size: 0.65rem;
font-weight: 700;
padding: 2px 6px;
border-radius: 3px;
white-space: nowrap;
letter-spacing: 0.4px;
text-transform: uppercase;
pointer-events: none;
}
}
1 change: 0 additions & 1 deletion assets/scss/_transactions-cards.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

.transactions-cards {
width: 100%;
display: block;

.cards-heading {
display: flex;
Expand Down
35 changes: 34 additions & 1 deletion components/ContentCard.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
<template>
<div class="entity-card">
<div class="entity-card" :class="{ 'is-default': isDefault }">
<div class="entity-icon-name" :class="{ 'no-icon': !icon }">
<component :is="resolvedIcon" v-if="icon" class="entity-icon" />
<span class="name">{{ name }}</span>
<span v-if="isDefault" class="default-badge" title="This is the default wallet">
Default
</span>
</div>
<div class="entity-description">
{{ description }}
Expand Down Expand Up @@ -32,12 +35,12 @@
import * as LucideIcons from 'lucide-vue-next';

const props = defineProps({
name: String,

Check warning on line 38 in components/ContentCard.vue

View workflow job for this annotation

GitHub Actions / Lint and format

Prop 'name' requires default value to be set
icon: {
type: String,
default: null
},
description: String,

Check warning on line 43 in components/ContentCard.vue

View workflow job for this annotation

GitHub Actions / Lint and format

Prop 'description' requires default value to be set
pageName: {
type: String,
required: true
Expand All @@ -45,6 +48,10 @@
type: {
type: String,
default: null
},
isDefault: {
type: Boolean,
default: false
}
});

Expand Down Expand Up @@ -86,11 +93,21 @@
min-height: 50px;
}

&.is-default {
background: rgba($success, 0.08);
border-left: 4px solid $success;
padding-left: calc($spacing-4 - 4px);
}

&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
background: #fff;

&.is-default {
background: rgba($success, 0.12);
}

.entity-icon {
transform: scale(1.1);
}
Expand Down Expand Up @@ -140,6 +157,22 @@
}
}

.default-badge {
display: inline-flex;
align-items: center;
justify-content: center;
background: $primary;
color: white;
font-size: 0.7rem;
font-weight: 700;
padding: 3px 8px;
border-radius: 4px;
white-space: nowrap;
flex-shrink: 0;
letter-spacing: 0.5px;
text-transform: uppercase;
}

&.no-icon {
padding-left: calc(24px + #{$spacing-2});

Expand Down
5 changes: 5 additions & 0 deletions components/ContentTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
:icon="entity.icon?.path || entity.icon?.content || entity.icon"
:description="entity.description"
:page-name="pageName"
:is-default="String(entity.id) === defaultItemId"
@edit="$emit('edit', entity)"
@delete="$emit('delete', entity)"
/>
Expand Down Expand Up @@ -119,6 +120,10 @@ const props = defineProps({
headerType: {
type: String,
default: 'default' // 'default', 'expense'
},
defaultItemId: {
type: String,
default: null
}
});

Expand Down
38 changes: 28 additions & 10 deletions components/TransactionForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,23 @@
@select="handlePartySelect"
/>

<SearchableDropdown
v-model="walletSearchQuery"
:label="isOutcomeSelected ? 'Wallet (sent from)' : 'Wallet (received to)'"
placeholder="Search wallet..."
:options="wallets"
:error="walletError ? 'Wallet is required.' : ''"
@select="handleWalletSelect"
/>
<div class="wallet-field-wrapper">
<SearchableDropdown
v-model="walletSearchQuery"
:label="isOutcomeSelected ? 'Wallet (sent from)' : 'Wallet (received to)'"
placeholder="Search wallet..."
:options="wallets"
:error="walletError ? 'Wallet is required.' : ''"
@select="handleWalletSelect"
/>
<span
v-if="isWalletDefault"
class="wallet-default-indicator"
title="This is your default wallet"
>
Default
</span>
</div>
</div>

<div class="form-transaction">
Expand Down Expand Up @@ -157,7 +166,8 @@ const selectedWalletId = ref('');
const selectedGroupId = ref(null);
const selectedAdditionalCategoryIds = ref([]);
const filesBase64 = ref([]);
const selectedCurrency = ref('XAF');
const sharedData = useSharedData();
const selectedCurrency = ref(sharedData.getDefaultCurrency.value || 'USD');

const dateError = ref(false);
const timeError = ref(false);
Expand Down Expand Up @@ -223,7 +233,7 @@ function onSubmit() {
emit('submit', payload);
}

const sharedData = useSharedData();
// sharedData declared above for default currency

const parties = computed(() => sharedData.parties.value);
const groups = computed(() => sharedData.groups.value);
Expand Down Expand Up @@ -252,6 +262,14 @@ const wallets = computed(() => {
});
});

const isWalletDefault = computed(() => {
if (!selectedWalletId.value) return false;
const defaultWallet = sharedData.getDefaultWallet.value;
if (!defaultWallet) return false;
const defaultId = String(defaultWallet.sync_state?.client_generated_id || defaultWallet.id);
return selectedWalletId.value === defaultId;
});

function handlePartySelect(party) {
formParty.value = party.name;
const partyId = party.sync_state?.client_generated_id || String(party.id);
Expand Down
Loading