Design fixes for dark mode #34
@ -2,6 +2,7 @@
|
|||||||
import { ref, watch } from "vue"
|
import { ref, watch } from "vue"
|
||||||
import { GET } from "../api";
|
import { GET } from "../api";
|
||||||
import { useBudgetsStore } from "../stores/budget";
|
import { useBudgetsStore } from "../stores/budget";
|
||||||
|
import Input from "./Input.vue";
|
||||||
|
|
||||||
export interface Suggestion {
|
export interface Suggestion {
|
||||||
ID: string
|
ID: string
|
||||||
@ -43,7 +44,9 @@ function load(text: String) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
function keypress(e: KeyboardEvent) {
|
function keypress(e: KeyboardEvent) {
|
||||||
if (e.key == "Enter") {
|
if (e.key != "Enter")
|
||||||
|
return;
|
||||||
|
|
||||||
const selected = Suggestions.value[0];
|
const selected = Suggestions.value[0];
|
||||||
selectElement(selected);
|
selectElement(selected);
|
||||||
const el = (<HTMLInputElement>e.target);
|
const el = (<HTMLInputElement>e.target);
|
||||||
@ -51,14 +54,15 @@ function keypress(e: KeyboardEvent) {
|
|||||||
const currentIndex = inputElements.indexOf(el);
|
const currentIndex = inputElements.indexOf(el);
|
||||||
const nextElement = inputElements[currentIndex < inputElements.length - 1 ? currentIndex + 1 : 0];
|
const nextElement = inputElements[currentIndex < inputElements.length - 1 ? currentIndex + 1 : 0];
|
||||||
(<HTMLInputElement>nextElement).focus();
|
(<HTMLInputElement>nextElement).focus();
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function selectElement(element: Suggestion) {
|
function selectElement(element: Suggestion) {
|
||||||
emit('update:id', element.ID);
|
emit('update:id', element.ID);
|
||||||
emit('update:text', element.Name);
|
emit('update:text', element.Name);
|
||||||
emit('update:type', element.Type);
|
emit('update:type', element.Type);
|
||||||
Suggestions.value = [];
|
Suggestions.value = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
function select(e: MouseEvent) {
|
function select(e: MouseEvent) {
|
||||||
const target = (<HTMLInputElement>e.target);
|
const target = (<HTMLInputElement>e.target);
|
||||||
const valueAttribute = target.attributes.getNamedItem("value");
|
const valueAttribute = target.attributes.getNamedItem("value");
|
||||||
@ -68,6 +72,7 @@ function select(e: MouseEvent) {
|
|||||||
const selected = Suggestions.value.filter(x => x.ID == selectedID)[0];
|
const selected = Suggestions.value.filter(x => x.ID == selectedID)[0];
|
||||||
selectElement(selected);
|
selectElement(selected);
|
||||||
};
|
};
|
||||||
|
|
||||||
function clear() {
|
function clear() {
|
||||||
emit('update:id', null);
|
emit('update:id', null);
|
||||||
emit('update:text', SearchQuery.value);
|
emit('update:text', SearchQuery.value);
|
||||||
@ -77,14 +82,15 @@ function clear() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<input
|
<Input
|
||||||
|
type="text"
|
||||||
class="border-b-2 border-black"
|
class="border-b-2 border-black"
|
||||||
@keypress="keypress"
|
@keypress="keypress"
|
||||||
v-if="id == undefined"
|
v-if="id == undefined"
|
||||||
v-model="SearchQuery"
|
v-model="SearchQuery"
|
||||||
/>
|
/>
|
||||||
<span @click="clear" v-if="id != undefined" class="bg-gray-300">{{ text }}</span>
|
<span @click="clear" v-if="id != undefined" class="bg-gray-300 dark:bg-gray-700">{{ text }}</span>
|
||||||
<div v-if="Suggestions.length > 0" class="absolute bg-gray-400 w-64 p-2">
|
<div v-if="Suggestions.length > 0" class="absolute bg-gray-400 dark:bg-gray-600 w-64 p-2">
|
||||||
<span
|
<span
|
||||||
v-for="suggestion in Suggestions"
|
v-for="suggestion in Suggestions"
|
||||||
class="block"
|
class="block"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import Input from './Input.vue';
|
||||||
const props = defineProps(["modelValue"]);
|
const props = defineProps(["modelValue"]);
|
||||||
const emit = defineEmits(['update:modelValue']);
|
const emit = defineEmits(['update:modelValue']);
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ function selectAll(event: FocusEvent) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<input
|
<Input
|
||||||
type="date"
|
type="date"
|
||||||
ref="input"
|
ref="input"
|
||||||
v-bind:value="dateToYYYYMMDD(modelValue)"
|
v-bind:value="dateToYYYYMMDD(modelValue)"
|
||||||
|
10
web/src/components/Input.vue
Normal file
10
web/src/components/Input.vue
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
const props = defineProps(["modelValue"]);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<input
|
||||||
|
v-model="modelValue"
|
||||||
|
@input="$emit('update:modelValue', ($event.target as HTMLInputElement)?.value)"
|
||||||
|
class="dark:bg-slate-900">
|
||||||
|
</template>
|
@ -4,6 +4,8 @@ import Autocomplete from './Autocomplete.vue'
|
|||||||
import { useAccountStore } from '../stores/budget-account'
|
import { useAccountStore } from '../stores/budget-account'
|
||||||
import DateInput from "./DateInput.vue";
|
import DateInput from "./DateInput.vue";
|
||||||
import { useTransactionsStore } from "../stores/transactions";
|
import { useTransactionsStore } from "../stores/transactions";
|
||||||
|
import Input from "./Input.vue";
|
||||||
|
import Button from "./Button.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
transactionid: string
|
transactionid: string
|
||||||
@ -37,28 +39,28 @@ function saveTransaction(e: MouseEvent) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="width: 90px;" class="text-sm">
|
<td class="text-sm">
|
||||||
<DateInput class="border-b-2 border-black" v-model="TX.Date" />
|
<DateInput class="border-b-2 border-black" v-model="TX.Date" />
|
||||||
</td>
|
</td>
|
||||||
<td style="max-width: 150px;">
|
<td>
|
||||||
<Autocomplete v-model:text="TX.Payee" v-model:id="TX.PayeeID" v-model:type="payeeType" model="payees" />
|
<Autocomplete v-model:text="TX.Payee" v-model:id="TX.PayeeID" v-model:type="payeeType" model="payees" />
|
||||||
</td>
|
</td>
|
||||||
<td style="max-width: 200px;">
|
<td>
|
||||||
<Autocomplete v-model:text="TX.Category" v-model:id="TX.CategoryID" model="categories" />
|
<Autocomplete v-model:text="TX.Category" v-model:id="TX.CategoryID" model="categories" />
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input class="block w-full border-b-2 border-black" type="text" v-model="TX.Memo" />
|
<Input class="block w-full border-b-2 border-black" type="text" v-model="TX.Memo" />
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 80px;" class="text-right">
|
<td class="text-right">
|
||||||
<input
|
<Input
|
||||||
class="text-right block w-full border-b-2 border-black"
|
class="text-right block w-full border-b-2 border-black"
|
||||||
type="currency"
|
type="currency"
|
||||||
v-model="TX.Amount"
|
v-model="TX.Amount"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 20px;">
|
<td>
|
||||||
<input type="submit" @click="saveTransaction" value="Save" />
|
<Button class="bg-blue-500" @click="saveTransaction">Save</Button>
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 20px;"></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
@ -4,6 +4,7 @@ import Autocomplete from '../components/Autocomplete.vue'
|
|||||||
import { Transaction, useTransactionsStore } from "../stores/transactions";
|
import { Transaction, useTransactionsStore } from "../stores/transactions";
|
||||||
import DateInput from "./DateInput.vue";
|
import DateInput from "./DateInput.vue";
|
||||||
import Button from "./Button.vue";
|
import Button from "./Button.vue";
|
||||||
|
import Input from "./Input.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
budgetid: string
|
budgetid: string
|
||||||
@ -65,11 +66,11 @@ function saveTransaction(e: MouseEvent) {
|
|||||||
<Autocomplete v-model:text="TX.Category" v-model:id="TX.CategoryID" model="categories" />
|
<Autocomplete v-model:text="TX.Category" v-model:id="TX.CategoryID" model="categories" />
|
||||||
</td>
|
</td>
|
||||||
<td class="col-span-2">
|
<td class="col-span-2">
|
||||||
<input class="block w-full border-b-2 border-black" type="text" v-model="TX.Memo" />
|
<Input class="block w-full border-b-2 border-black" type="text" v-model="TX.Memo" />
|
||||||
</td>
|
</td>
|
||||||
<label class="md:hidden">Amount</label>
|
<label class="md:hidden">Amount</label>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
<input
|
<Input
|
||||||
class="text-right block w-full border-b-2 border-black"
|
class="text-right block w-full border-b-2 border-black"
|
||||||
type="currency"
|
type="currency"
|
||||||
v-model="TX.Amount"
|
v-model="TX.Amount"
|
||||||
|
@ -6,6 +6,7 @@ import Currency from "./Currency.vue";
|
|||||||
import TransactionEditRow from "./TransactionEditRow.vue";
|
import TransactionEditRow from "./TransactionEditRow.vue";
|
||||||
import { formatDate } from "../date";
|
import { formatDate } from "../date";
|
||||||
import { useAccountStore } from "../stores/budget-account";
|
import { useAccountStore } from "../stores/budget-account";
|
||||||
|
import Input from "./Input.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
transactionid: string,
|
transactionid: string,
|
||||||
@ -69,7 +70,7 @@ function getStatusSymbol() {
|
|||||||
{{ TX.GroupID ? "☀" : "" }}
|
{{ TX.GroupID ? "☀" : "" }}
|
||||||
{{ getStatusSymbol() }}
|
{{ getStatusSymbol() }}
|
||||||
<a @click="edit = true;">✎</a>
|
<a @click="edit = true;">✎</a>
|
||||||
<input v-if="Reconciling && TX.Status != 'Reconciled'" type="checkbox" v-model="TX.Reconciled" />
|
<Input v-if="Reconciling && TX.Status != 'Reconciled'" type="checkbox" v-model="TX.Reconciled" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<TransactionEditRow v-if="edit" :transactionid="TX.ID" @save="edit = false" />
|
<TransactionEditRow v-if="edit" :transactionid="TX.ID" @save="edit = false" />
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import Modal from '../components/Modal.vue';
|
import Modal from '../components/Modal.vue';
|
||||||
import { useAccountStore } from '../stores/budget-account';
|
import { useAccountStore } from '../stores/budget-account';
|
||||||
|
import Input from '../components/Input.vue';
|
||||||
|
|
||||||
const accountStore = useAccountStore();
|
const accountStore = useAccountStore();
|
||||||
const CurrentAccount = computed(() => accountStore.CurrentAccount);
|
const CurrentAccount = computed(() => accountStore.CurrentAccount);
|
||||||
@ -23,7 +24,7 @@ function openEditAccount(e : any) {
|
|||||||
<Modal button-text="Edit Account" @open="openEditAccount" @submit="editAccount">
|
<Modal button-text="Edit Account" @open="openEditAccount" @submit="editAccount">
|
||||||
<template v-slot:placeholder>✎</template>
|
<template v-slot:placeholder>✎</template>
|
||||||
<div class="mt-2 px-7 py-3">
|
<div class="mt-2 px-7 py-3">
|
||||||
<input
|
<Input
|
||||||
class="border-2"
|
class="border-2"
|
||||||
type="text"
|
type="text"
|
||||||
v-model="accountName"
|
v-model="accountName"
|
||||||
@ -32,7 +33,7 @@ function openEditAccount(e : any) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 px-7 py-3">
|
<div class="mt-2 px-7 py-3">
|
||||||
<input
|
<Input
|
||||||
class="border-2"
|
class="border-2"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
v-model="accountOnBudget"
|
v-model="accountOnBudget"
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import Modal from '../components/Modal.vue';
|
import Modal from '../components/Modal.vue';
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useBudgetsStore } from '../stores/budget';
|
import { useBudgetsStore } from '../stores/budget';
|
||||||
|
import Input from '../components/Input.vue';
|
||||||
|
|
||||||
const budgetName = ref("");
|
const budgetName = ref("");
|
||||||
function saveBudget() {
|
function saveBudget() {
|
||||||
@ -12,7 +13,7 @@ function saveBudget() {
|
|||||||
<template>
|
<template>
|
||||||
<Modal button-text="New Budget" @submit="saveBudget">
|
<Modal button-text="New Budget" @submit="saveBudget">
|
||||||
<div class="mt-2 px-7 py-3">
|
<div class="mt-2 px-7 py-3">
|
||||||
<input class="border-2" type="text" v-model="budgetName" placeholder="Budget name" required />
|
<Input class="border-2" type="text" v-model="budgetName" placeholder="Budget name" required />
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
@ -8,6 +8,7 @@ import EditAccount from "../dialogs/EditAccount.vue";
|
|||||||
import Button from "../components/Button.vue";
|
import Button from "../components/Button.vue";
|
||||||
import { useTransactionsStore } from "../stores/transactions";
|
import { useTransactionsStore } from "../stores/transactions";
|
||||||
import Modal from "../components/Modal.vue";
|
import Modal from "../components/Modal.vue";
|
||||||
|
import Input from "../components/Input.vue";
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
budgetid: string
|
budgetid: string
|
||||||
@ -73,7 +74,7 @@ function createReconcilationTransaction() {
|
|||||||
<Currency :value="transactions.ReconcilingBalance" />your current balance?
|
<Currency :value="transactions.ReconcilingBalance" />your current balance?
|
||||||
<Button class="bg-blue-500 mx-3 py-2" @click="submitReconcilation">Yes!</Button>
|
<Button class="bg-blue-500 mx-3 py-2" @click="submitReconcilation">Yes!</Button>
|
||||||
<br />No, it's:
|
<br />No, it's:
|
||||||
<input class="text-right" type="number" v-model="TargetReconcilingBalance" />
|
<Input class="text-right" type="number" v-model="TargetReconcilingBalance" />
|
||||||
Difference:
|
Difference:
|
||||||
<Currency :value="transactions.ReconcilingBalance - TargetReconcilingBalance" />
|
<Currency :value="transactions.ReconcilingBalance - TargetReconcilingBalance" />
|
||||||
<Button
|
<Button
|
||||||
@ -93,7 +94,7 @@ function createReconcilationTransaction() {
|
|||||||
<td>Memo</td>
|
<td>Memo</td>
|
||||||
<td class="text-right">Amount</td>
|
<td class="text-right">Amount</td>
|
||||||
<td style="width: 80px;">
|
<td style="width: 80px;">
|
||||||
<input v-if="transactions.Reconciling" type="checkbox" @input="setReconciled" />
|
<Input v-if="transactions.Reconciling" type="checkbox" @input="setReconciled" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<TransactionInputRow class="hidden md:table-row" :budgetid="budgetid" :accountid="accountid" />
|
<TransactionInputRow class="hidden md:table-row" :budgetid="budgetid" :accountid="accountid" />
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { useSessionStore } from "../stores/session";
|
import { useSessionStore } from "../stores/session";
|
||||||
|
import Input from "../components/Input.vue";
|
||||||
|
|
||||||
const error = ref("");
|
const error = ref("");
|
||||||
const login = ref({ user: "", password: "" });
|
const login = ref({ user: "", password: "" });
|
||||||
@ -28,10 +29,10 @@ function formSubmit(e: MouseEvent) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" v-model="login.user"
|
<Input type="text" v-model="login.user"
|
||||||
placeholder="Username"
|
placeholder="Username"
|
||||||
class="border-2 border-black rounded-lg block px-2 my-2 w-48" />
|
class="border-2 border-black rounded-lg block px-2 my-2 w-48" />
|
||||||
<input type="password" v-model="login.password"
|
<Input type="password" v-model="login.password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
class="border-2 border-black rounded-lg block px-2 my-2 w-48" />
|
class="border-2 border-black rounded-lg block px-2 my-2 w-48" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { useSessionStore } from "../stores/session";
|
import { useSessionStore } from "../stores/session";
|
||||||
|
import Input from "../components/Input.vue";
|
||||||
|
|
||||||
const error = ref("");
|
const error = ref("");
|
||||||
const login = ref({ email: "", password: "", name: "" });
|
const login = ref({ email: "", password: "", name: "" });
|
||||||
@ -28,13 +29,13 @@ function formSubmit(e: MouseEvent) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" v-model="login.name"
|
<Input type="text" v-model="login.name"
|
||||||
placeholder="Name"
|
placeholder="Name"
|
||||||
class="border-2 border-black rounded-lg block px-2 my-2 w-48" />
|
class="border-2 border-black rounded-lg block px-2 my-2 w-48" />
|
||||||
<input type="text" v-model="login.email"
|
<Input type="text" v-model="login.email"
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
class="border-2 border-black rounded-lg block px-2 my-2 w-48" />
|
class="border-2 border-black rounded-lg block px-2 my-2 w-48" />
|
||||||
<input type="password" v-model="login.password"
|
<Input type="password" v-model="login.password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
class="border-2 border-black rounded-lg block px-2 my-2 w-48" />
|
class="border-2 border-black rounded-lg block px-2 my-2 w-48" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,6 +7,7 @@ import { useSessionStore } from "../stores/session";
|
|||||||
import Card from "../components/Card.vue";
|
import Card from "../components/Card.vue";
|
||||||
import Button from "../components/Button.vue";
|
import Button from "../components/Button.vue";
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
|
import Input from "../components/Input.vue";
|
||||||
|
|
||||||
const transactionsFile = ref<File | undefined>(undefined);
|
const transactionsFile = ref<File | undefined>(undefined);
|
||||||
const assignmentsFile = ref<File | undefined>(undefined);
|
const assignmentsFile = ref<File | undefined>(undefined);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user