generated from dave/wails-template
	Compare commits
	
		
			16 Commits
		
	
	
		
			de7c2cc82c
			...
			1.0.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 236b113c10 | |||
| 4ee622e65e | |||
| 2ac082f230 | |||
| 45030f8634 | |||
| 79b89a01e5 | |||
| 37a0c52464 | |||
| f018459818 | |||
| c5613ee0cc | |||
| 8c10540309 | |||
| f96c0ba8b5 | |||
| 46b50b6bd3 | |||
| e33dea3e4b | |||
| 5b00b68a88 | |||
| 69eee93cff | |||
| 9cbaf7880b | |||
| c17e25c358 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -3,3 +3,5 @@ frontend/dist | |||||||
| build | build | ||||||
| bills.db | bills.db | ||||||
| main.log | main.log | ||||||
|  | bills.db-shm | ||||||
|  | bills.db-wal | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								app.go
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								app.go
									
									
									
									
									
								
							| @@ -3,6 +3,8 @@ package main | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/wailsapp/wails/v2/pkg/runtime" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // App struct | // App struct | ||||||
| @@ -20,6 +22,9 @@ func NewApp() *App { | |||||||
| func (a *App) startup(ctx context.Context) { | func (a *App) startup(ctx context.Context) { | ||||||
| 	a.ctx = ctx | 	a.ctx = ctx | ||||||
| } | } | ||||||
|  | func (a *App) Close() { | ||||||
|  | 	runtime.Quit(a.ctx) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (a *App) GetBills() WailsBills { | func (a *App) GetBills() WailsBills { | ||||||
| 	res := WailsBills{} | 	res := WailsBills{} | ||||||
| @@ -57,3 +62,11 @@ func (a *App) SetPaid(billid int64, month time.Time) WailsPayment { | |||||||
| 	res.Data = payment | 	res.Data = payment | ||||||
| 	return res | 	return res | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // These exist only so that wails generates models for Bill and Payment | ||||||
|  | func (a *App) EmptyBill() Bill { | ||||||
|  | 	return Bill{} | ||||||
|  | } | ||||||
|  | func (a *App) EmptyPayment() Payment { | ||||||
|  | 	return Payment{} | ||||||
|  | } | ||||||
| @@ -1,12 +1,15 @@ | |||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html lang="en"> | <html lang="en"> | ||||||
|  |  | ||||||
| <head> | <head> | ||||||
|     <meta charset="UTF-8" /> |     <meta charset="UTF-8" /> | ||||||
|     <meta content="width=device-width, initial-scale=1.0" name="viewport" /> |     <meta content="width=device-width, initial-scale=1.0" name="viewport" /> | ||||||
|     <title>wails-template</title> |     <title>bill-manager</title> | ||||||
| </head> | </head> | ||||||
|  |  | ||||||
| <body> | <body> | ||||||
|     <div id="app"></div> |     <div id="app"></div> | ||||||
|     <script src="./src/main.ts" type="module"></script> |     <script src="./src/main.ts" type="module"></script> | ||||||
| </body> | </body> | ||||||
|  |  | ||||||
| </html> | </html> | ||||||
| @@ -1,10 +1,29 @@ | |||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| 	import Header from "$lib/components/Header.svelte"; | 	import { Toaster } from "svelte-sonner"; | ||||||
| 	import Router from "$lib/router/Router.svelte"; | 	import Router from "$lib/router/Router.svelte"; | ||||||
|  | 	import { Close } from "$wails/main/App"; | ||||||
|  | 	import { scrollingTimeFrameStore } from "$lib/store/scrollingTimeFrameStore"; | ||||||
|  |  | ||||||
|  | 	function keyDown(event: KeyboardEvent) { | ||||||
|  | 		if (event.ctrlKey && event.key == "r") { | ||||||
|  | 			window.location.reload(); | ||||||
|  | 		} | ||||||
|  | 		if (event.ctrlKey && event.key == "w") { | ||||||
|  | 			Close(); | ||||||
|  | 		} | ||||||
|  | 		if (event.key == "ArrowLeft") { | ||||||
|  | 			scrollingTimeFrameStore.prev(); | ||||||
|  | 		} | ||||||
|  | 		if (event.key == "ArrowRight") { | ||||||
|  | 			scrollingTimeFrameStore.next(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
|  | <svelte:window on:keydown={keyDown} /> | ||||||
|  | <Toaster theme="dark" expand visibleToasts={9} /> | ||||||
| <template> | <template> | ||||||
| 	<Header /> | 	<!-- <Header /> --> | ||||||
| 	<main class="flex-1"> | 	<main class="flex-1"> | ||||||
| 		<Router /> | 		<Router /> | ||||||
| 	</main> | 	</main> | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								frontend/src/lib/components/PaymentBillComp.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								frontend/src/lib/components/PaymentBillComp.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | <script lang="ts"> | ||||||
|  | 	import { type PaymentBill } from "$lib/types"; | ||||||
|  | 	import { SetPaid } from "$wails/main/App"; | ||||||
|  | 	import { toast } from "svelte-sonner"; | ||||||
|  |  | ||||||
|  | 	export let paymentBill: PaymentBill = { | ||||||
|  | 		id: -1, | ||||||
|  | 		name: "none", | ||||||
|  | 		payment: null, | ||||||
|  | 	}; | ||||||
|  | 	export let monthFor: Date = new Date(); | ||||||
|  |  | ||||||
|  | 	let paymentDate: string = ""; | ||||||
|  | 	$: { | ||||||
|  | 		if (!!paymentBill.payment?.paymentDate) { | ||||||
|  | 			// @ts-ignore Yes split exists... The type is time.Time but it's actually a string | ||||||
|  | 			// Because typescript is a worthless waste of bytes | ||||||
|  | 			// And I don't know how to properly convert time.Time to Date or String | ||||||
|  | 			// So I'm doing this bullshit | ||||||
|  | 			paymentDate = paymentBill.payment!.paymentDate.split("T")[0]; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	async function doPaid(event: MouseEvent) { | ||||||
|  | 		const res = await SetPaid(paymentBill.id, monthFor); | ||||||
|  | 		if (!res.success) { | ||||||
|  | 			toast.error(`failed setting paid for ${paymentBill.id} and month ${monthFor} with error ${res.error}`); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		paymentBill.payment = res.data; | ||||||
|  | 	} | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <template> | ||||||
|  | 	<div class="grid grid-cols-2 w-full text-start px-3 text-xl"> | ||||||
|  | 		<p class={paymentBill.payment == null ? "text-red-700" : ""}>{paymentBill.name}</p> | ||||||
|  | 		<!-- svelte-ignore a11y-click-events-have-key-events --> | ||||||
|  | 		<p | ||||||
|  | 			class="h-[1.6em] cursor-pointer border-2 border-transparent hover:border-solid hover:border-sky-500" | ||||||
|  | 			on:click={doPaid} | ||||||
|  | 		> | ||||||
|  | 			{paymentDate} | ||||||
|  | 		</p> | ||||||
|  | 	</div> | ||||||
|  | </template> | ||||||
							
								
								
									
										49
									
								
								frontend/src/lib/components/Payments.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								frontend/src/lib/components/Payments.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | <script lang="ts"> | ||||||
|  | 	import { billsStore } from "$lib/store/billsStore"; | ||||||
|  | 	import { type PaymentBill } from "$lib/types"; | ||||||
|  | 	import { main } from "$wails/models"; | ||||||
|  | 	import { toast } from "svelte-sonner"; | ||||||
|  | 	import PaymentBillComp from "./PaymentBillComp.svelte"; | ||||||
|  |  | ||||||
|  | 	export let payments: main.Payment[] = []; | ||||||
|  | 	export let date: Date = new Date(); | ||||||
|  | 	let dateString: string = date.toISOString() | ||||||
|  | 	$: { | ||||||
|  | 		dateString = date.toISOString().split("T")[0] | ||||||
|  | 		dateString = dateString.split("-").slice(0, 2).join("-"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const paymentsModel: { [key: number]: PaymentBill } = {}; | ||||||
|  | 	for (const bill of $billsStore) { | ||||||
|  | 		paymentsModel[bill[1].id] = { | ||||||
|  | 			id: bill[1].id, | ||||||
|  | 			name: bill[1].name, | ||||||
|  | 			payment: null, | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | 	for (const payment of payments) { | ||||||
|  | 		const bill = $billsStore.get(payment.billId); | ||||||
|  | 		if (!!!bill) { | ||||||
|  | 			toast.error(`Bill not found for id ${payment.billId}`); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		paymentsModel[bill.id] = { | ||||||
|  | 			id: bill.id, | ||||||
|  | 			name: bill.name, | ||||||
|  | 			payment: payment, | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <template> | ||||||
|  | 	<div class="border-double border-2 border-gray-500 m-1"> | ||||||
|  | 		<div class="text-4xl font-bold"> | ||||||
|  | 			{dateString} | ||||||
|  | 		</div> | ||||||
|  | 		<div class=""> | ||||||
|  | 			{#each Object.values(paymentsModel) as payment} | ||||||
|  | 				<PaymentBillComp paymentBill={payment} monthFor={date} /> | ||||||
|  | 			{/each} | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </template> | ||||||
| @@ -1,7 +1,26 @@ | |||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
|  | 	import Payments from "$lib/components/Payments.svelte"; | ||||||
|  | 	import { scrollingTimeFrameStore } from "$lib/store/scrollingTimeFrameStore"; | ||||||
|  | 	import { lastMonthPaymentsStore } from "$lib/store/lastMonthPaymentsStore"; | ||||||
|  | 	import { thisMonthPaymentsStore } from "$lib/store/thisMonthPaymentsStore"; | ||||||
|  |  | ||||||
|  | 	let forceupdate = false; | ||||||
|  | 	thisMonthPaymentsStore.subscribe(() => { | ||||||
|  | 		forceupdate = !forceupdate; | ||||||
|  | 	}); | ||||||
|  | 	lastMonthPaymentsStore.subscribe(() => { | ||||||
|  | 		forceupdate = !forceupdate; | ||||||
|  | 	}); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <template> | <template> | ||||||
| 	Hello, world | 	<div class="grid grid-cols-2"> | ||||||
|  | 		{#if forceupdate} | ||||||
|  | 			<Payments date={$scrollingTimeFrameStore.from} payments={$lastMonthPaymentsStore} /> | ||||||
|  | 			<Payments date={$scrollingTimeFrameStore.to} payments={$thisMonthPaymentsStore} /> | ||||||
|  | 		{:else} | ||||||
|  | 			<Payments date={$scrollingTimeFrameStore.from} payments={$lastMonthPaymentsStore} /> | ||||||
|  | 			<Payments date={$scrollingTimeFrameStore.to} payments={$thisMonthPaymentsStore} /> | ||||||
|  | 		{/if} | ||||||
|  | 	</div> | ||||||
| </template> | </template> | ||||||
							
								
								
									
										37
									
								
								frontend/src/lib/store/billsStore.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								frontend/src/lib/store/billsStore.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | import { type Writable, writable } from "svelte/store"; | ||||||
|  | import { GetBills } from "$wails/main/App"; | ||||||
|  | import { main } from "$wails/models"; | ||||||
|  | import { toast } from "svelte-sonner"; | ||||||
|  |  | ||||||
|  | async function createStore(): Promise<Writable<Map<number, main.Bill>> & { refresh: Function }> { | ||||||
|  | 	const bills: Map<number, main.Bill> = new Map<number, main.Bill>(); | ||||||
|  | 	const res = await GetBills(); | ||||||
|  | 	if (!res.success) { | ||||||
|  | 		toast.error("Error getting bills " + res.error); | ||||||
|  | 	} else { | ||||||
|  | 		for (let i = 0; i < res.data.length; i++) { | ||||||
|  | 			const bill = res.data[i]; | ||||||
|  | 			bills.set(bill.id, bill); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const { subscribe, update, set } = writable(bills); | ||||||
|  | 	return { | ||||||
|  | 		subscribe, | ||||||
|  | 		update, | ||||||
|  | 		set, | ||||||
|  | 		refresh: async () => { | ||||||
|  | 			const res = await GetBills(); | ||||||
|  | 			if (!res.success) { | ||||||
|  | 				toast.error("Error getting bills " + res.error); | ||||||
|  | 			} else { | ||||||
|  | 				for (let i = 0; i < res.data.length; i++) { | ||||||
|  | 					const bill = res.data[i]; | ||||||
|  | 					bills.set(bill.id, bill); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export const billsStore = await createStore(); | ||||||
							
								
								
									
										34
									
								
								frontend/src/lib/store/lastMonthPaymentsStore.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								frontend/src/lib/store/lastMonthPaymentsStore.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | import { get, type Writable, writable } from "svelte/store"; | ||||||
|  | import { GetPaymentsForMonth } from "$wails/main/App"; | ||||||
|  | import { main } from "$wails/models"; | ||||||
|  | import { toast } from "svelte-sonner"; | ||||||
|  | import { scrollingTimeFrameStore } from "$lib/store/scrollingTimeFrameStore"; | ||||||
|  |  | ||||||
|  | async function createStore(): Promise<Writable<main.Payment[]>> { | ||||||
|  | 	const payments: main.Payment[] = []; | ||||||
|  | 	const res = await GetPaymentsForMonth(get(scrollingTimeFrameStore).from); | ||||||
|  | 	if (!res.success) { | ||||||
|  | 		toast.error("Error getting payments " + res.error); | ||||||
|  | 	} else { | ||||||
|  | 		payments.push(...res.data); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const { subscribe, update, set } = writable(payments); | ||||||
|  | 	return { | ||||||
|  | 		subscribe, | ||||||
|  | 		update, | ||||||
|  | 		set, | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const lastMonthPaymentsStore = await createStore(); | ||||||
|  | scrollingTimeFrameStore.subscribe(async (timeframe) => { | ||||||
|  | 	const res = await GetPaymentsForMonth(timeframe.from); | ||||||
|  | 	if (!res.success) { | ||||||
|  | 		toast.error("Error getting payments " + res.error); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	lastMonthPaymentsStore.set(res.data); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | export { lastMonthPaymentsStore }; | ||||||
							
								
								
									
										31
									
								
								frontend/src/lib/store/scrollingTimeFrameStore.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								frontend/src/lib/store/scrollingTimeFrameStore.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | import { type ScrollingTimeframe } from "$lib/types"; | ||||||
|  | import { type Writable, writable } from "svelte/store"; | ||||||
|  |  | ||||||
|  | async function createStore(): Promise<Writable<ScrollingTimeframe> & { next: Function; prev: Function }> { | ||||||
|  | 	const thism = new Date(); | ||||||
|  | 	const lastm = new Date(); | ||||||
|  | 	lastm.setMonth(thism.getMonth() - 1); | ||||||
|  |  | ||||||
|  | 	const { subscribe, update, set } = writable({ from: lastm, to: thism }); | ||||||
|  | 	return { | ||||||
|  | 		subscribe, | ||||||
|  | 		update, | ||||||
|  | 		set, | ||||||
|  | 		next: () => { | ||||||
|  | 			update((frame: ScrollingTimeframe) => { | ||||||
|  | 				frame.from.setMonth(frame.from.getMonth() + 1); | ||||||
|  | 				frame.to.setMonth(frame.to.getMonth() + 1); | ||||||
|  | 				return frame; | ||||||
|  | 			}); | ||||||
|  | 		}, | ||||||
|  | 		prev: () => { | ||||||
|  | 			update((frame: ScrollingTimeframe) => { | ||||||
|  | 				frame.from.setMonth(frame.from.getMonth() - 1); | ||||||
|  | 				frame.to.setMonth(frame.to.getMonth() - 1); | ||||||
|  | 				return frame; | ||||||
|  | 			}); | ||||||
|  | 		}, | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export const scrollingTimeFrameStore = await createStore(); | ||||||
							
								
								
									
										34
									
								
								frontend/src/lib/store/thisMonthPaymentsStore.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								frontend/src/lib/store/thisMonthPaymentsStore.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | import { get, type Writable, writable } from "svelte/store"; | ||||||
|  | import { GetPaymentsForMonth } from "$wails/main/App"; | ||||||
|  | import { main } from "$wails/models"; | ||||||
|  | import { toast } from "svelte-sonner"; | ||||||
|  | import { scrollingTimeFrameStore } from "$lib/store/scrollingTimeFrameStore"; | ||||||
|  |  | ||||||
|  | async function createStore(): Promise<Writable<main.Payment[]>> { | ||||||
|  | 	const payments: main.Payment[] = []; | ||||||
|  | 	const res = await GetPaymentsForMonth(get(scrollingTimeFrameStore).to); | ||||||
|  | 	if (!res.success) { | ||||||
|  | 		toast.error("Error getting payments " + res.error); | ||||||
|  | 	} else { | ||||||
|  | 		payments.push(...res.data); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const { subscribe, update, set } = writable(payments); | ||||||
|  | 	return { | ||||||
|  | 		subscribe, | ||||||
|  | 		update, | ||||||
|  | 		set, | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const thisMonthPaymentsStore = await createStore(); | ||||||
|  | scrollingTimeFrameStore.subscribe(async (timeframe) => { | ||||||
|  | 	const res = await GetPaymentsForMonth(timeframe.to); | ||||||
|  | 	if (!res.success) { | ||||||
|  | 		toast.error("Error getting payments " + res.error); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	thisMonthPaymentsStore.set(res.data); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | export { thisMonthPaymentsStore }; | ||||||
							
								
								
									
										11
									
								
								frontend/src/lib/types.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								frontend/src/lib/types.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | import { main } from "$wails/models"; | ||||||
|  |  | ||||||
|  | export type PaymentBill = { | ||||||
|  | 	id: number; | ||||||
|  | 	name: string; | ||||||
|  | 	payment: main.Payment|null; | ||||||
|  | }; | ||||||
|  | export type ScrollingTimeframe = { | ||||||
|  | 	from: Date; | ||||||
|  | 	to: Date; | ||||||
|  | } | ||||||
| @@ -1,3 +1,7 @@ | |||||||
|  | @tailwind base; | ||||||
|  | @tailwind components; | ||||||
|  | @tailwind utilities; | ||||||
|  |  | ||||||
| html { | html { | ||||||
|     background-color: rgba(27, 38, 54, 1); |     background-color: rgba(27, 38, 54, 1); | ||||||
|     text-align: center; |     text-align: center; | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								frontend/wailsjs/go/main/App.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								frontend/wailsjs/go/main/App.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -3,6 +3,12 @@ | |||||||
| import {main} from '../models'; | import {main} from '../models'; | ||||||
| import {time} from '../models'; | import {time} from '../models'; | ||||||
|  |  | ||||||
|  | export function Close():Promise<void>; | ||||||
|  |  | ||||||
|  | export function EmptyBill():Promise<main.Bill>; | ||||||
|  |  | ||||||
|  | export function EmptyPayment():Promise<main.Payment>; | ||||||
|  |  | ||||||
| export function GetBills():Promise<main.WailsBills>; | export function GetBills():Promise<main.WailsBills>; | ||||||
|  |  | ||||||
| export function GetPaymentsForMonth(arg1:time.Time):Promise<main.WailsPayments>; | export function GetPaymentsForMonth(arg1:time.Time):Promise<main.WailsPayments>; | ||||||
|   | |||||||
| @@ -2,6 +2,18 @@ | |||||||
| // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL | // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL | ||||||
| // This file is automatically generated. DO NOT EDIT | // This file is automatically generated. DO NOT EDIT | ||||||
|  |  | ||||||
|  | export function Close() { | ||||||
|  |   return window['go']['main']['App']['Close'](); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export function EmptyBill() { | ||||||
|  |   return window['go']['main']['App']['EmptyBill'](); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export function EmptyPayment() { | ||||||
|  |   return window['go']['main']['App']['EmptyPayment'](); | ||||||
|  | } | ||||||
|  |  | ||||||
| export function GetBills() { | export function GetBills() { | ||||||
|   return window['go']['main']['App']['GetBills'](); |   return window['go']['main']['App']['GetBills'](); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,7 +1,59 @@ | |||||||
| export namespace main { | export namespace main { | ||||||
| 	 | 	 | ||||||
| 	export class WailsBills { | 	export class Bill { | ||||||
|  | 	    id: number; | ||||||
|  | 	    name: string; | ||||||
| 	 | 	 | ||||||
|  | 	    static createFrom(source: any = {}) { | ||||||
|  | 	        return new Bill(source); | ||||||
|  | 	    } | ||||||
|  | 	 | ||||||
|  | 	    constructor(source: any = {}) { | ||||||
|  | 	        if ('string' === typeof source) source = JSON.parse(source); | ||||||
|  | 	        this.id = source["id"]; | ||||||
|  | 	        this.name = source["name"]; | ||||||
|  | 	    } | ||||||
|  | 	} | ||||||
|  | 	export class Payment { | ||||||
|  | 	    id: number; | ||||||
|  | 	    billId: number; | ||||||
|  | 	    monthFor: time.Time; | ||||||
|  | 	    paymentDate: time.Time; | ||||||
|  | 	 | ||||||
|  | 	    static createFrom(source: any = {}) { | ||||||
|  | 	        return new Payment(source); | ||||||
|  | 	    } | ||||||
|  | 	 | ||||||
|  | 	    constructor(source: any = {}) { | ||||||
|  | 	        if ('string' === typeof source) source = JSON.parse(source); | ||||||
|  | 	        this.id = source["id"]; | ||||||
|  | 	        this.billId = source["billId"]; | ||||||
|  | 	        this.monthFor = this.convertValues(source["monthFor"], time.Time); | ||||||
|  | 	        this.paymentDate = this.convertValues(source["paymentDate"], time.Time); | ||||||
|  | 	    } | ||||||
|  | 	 | ||||||
|  | 		convertValues(a: any, classs: any, asMap: boolean = false): any { | ||||||
|  | 		    if (!a) { | ||||||
|  | 		        return a; | ||||||
|  | 		    } | ||||||
|  | 		    if (a.slice && a.map) { | ||||||
|  | 		        return (a as any[]).map(elem => this.convertValues(elem, classs)); | ||||||
|  | 		    } else if ("object" === typeof a) { | ||||||
|  | 		        if (asMap) { | ||||||
|  | 		            for (const key of Object.keys(a)) { | ||||||
|  | 		                a[key] = new classs(a[key]); | ||||||
|  | 		            } | ||||||
|  | 		            return a; | ||||||
|  | 		        } | ||||||
|  | 		        return new classs(a); | ||||||
|  | 		    } | ||||||
|  | 		    return a; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	export class WailsBills { | ||||||
|  | 	    data: Bill[]; | ||||||
|  | 	    success: boolean; | ||||||
|  | 	    error: string; | ||||||
| 	 | 	 | ||||||
| 	    static createFrom(source: any = {}) { | 	    static createFrom(source: any = {}) { | ||||||
| 	        return new WailsBills(source); | 	        return new WailsBills(source); | ||||||
| @@ -9,11 +61,33 @@ export namespace main { | |||||||
| 	 | 	 | ||||||
| 	    constructor(source: any = {}) { | 	    constructor(source: any = {}) { | ||||||
| 	        if ('string' === typeof source) source = JSON.parse(source); | 	        if ('string' === typeof source) source = JSON.parse(source); | ||||||
|  | 	        this.data = this.convertValues(source["data"], Bill); | ||||||
|  | 	        this.success = source["success"]; | ||||||
|  | 	        this.error = source["error"]; | ||||||
|  | 	    } | ||||||
| 	 | 	 | ||||||
|  | 		convertValues(a: any, classs: any, asMap: boolean = false): any { | ||||||
|  | 		    if (!a) { | ||||||
|  | 		        return a; | ||||||
|  | 		    } | ||||||
|  | 		    if (a.slice && a.map) { | ||||||
|  | 		        return (a as any[]).map(elem => this.convertValues(elem, classs)); | ||||||
|  | 		    } else if ("object" === typeof a) { | ||||||
|  | 		        if (asMap) { | ||||||
|  | 		            for (const key of Object.keys(a)) { | ||||||
|  | 		                a[key] = new classs(a[key]); | ||||||
|  | 		            } | ||||||
|  | 		            return a; | ||||||
|  | 		        } | ||||||
|  | 		        return new classs(a); | ||||||
|  | 		    } | ||||||
|  | 		    return a; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	export class WailsPayment { | 	export class WailsPayment { | ||||||
| 	 | 	    data: Payment; | ||||||
|  | 	    success: boolean; | ||||||
|  | 	    error: string; | ||||||
| 	 | 	 | ||||||
| 	    static createFrom(source: any = {}) { | 	    static createFrom(source: any = {}) { | ||||||
| 	        return new WailsPayment(source); | 	        return new WailsPayment(source); | ||||||
| @@ -21,11 +95,33 @@ export namespace main { | |||||||
| 	 | 	 | ||||||
| 	    constructor(source: any = {}) { | 	    constructor(source: any = {}) { | ||||||
| 	        if ('string' === typeof source) source = JSON.parse(source); | 	        if ('string' === typeof source) source = JSON.parse(source); | ||||||
|  | 	        this.data = this.convertValues(source["data"], Payment); | ||||||
|  | 	        this.success = source["success"]; | ||||||
|  | 	        this.error = source["error"]; | ||||||
|  | 	    } | ||||||
| 	 | 	 | ||||||
|  | 		convertValues(a: any, classs: any, asMap: boolean = false): any { | ||||||
|  | 		    if (!a) { | ||||||
|  | 		        return a; | ||||||
|  | 		    } | ||||||
|  | 		    if (a.slice && a.map) { | ||||||
|  | 		        return (a as any[]).map(elem => this.convertValues(elem, classs)); | ||||||
|  | 		    } else if ("object" === typeof a) { | ||||||
|  | 		        if (asMap) { | ||||||
|  | 		            for (const key of Object.keys(a)) { | ||||||
|  | 		                a[key] = new classs(a[key]); | ||||||
|  | 		            } | ||||||
|  | 		            return a; | ||||||
|  | 		        } | ||||||
|  | 		        return new classs(a); | ||||||
|  | 		    } | ||||||
|  | 		    return a; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	export class WailsPayments { | 	export class WailsPayments { | ||||||
| 	 | 	    data: Payment[]; | ||||||
|  | 	    success: boolean; | ||||||
|  | 	    error: string; | ||||||
| 	 | 	 | ||||||
| 	    static createFrom(source: any = {}) { | 	    static createFrom(source: any = {}) { | ||||||
| 	        return new WailsPayments(source); | 	        return new WailsPayments(source); | ||||||
| @@ -33,7 +129,27 @@ export namespace main { | |||||||
| 	 | 	 | ||||||
| 	    constructor(source: any = {}) { | 	    constructor(source: any = {}) { | ||||||
| 	        if ('string' === typeof source) source = JSON.parse(source); | 	        if ('string' === typeof source) source = JSON.parse(source); | ||||||
|  | 	        this.data = this.convertValues(source["data"], Payment); | ||||||
|  | 	        this.success = source["success"]; | ||||||
|  | 	        this.error = source["error"]; | ||||||
|  | 	    } | ||||||
| 	 | 	 | ||||||
|  | 		convertValues(a: any, classs: any, asMap: boolean = false): any { | ||||||
|  | 		    if (!a) { | ||||||
|  | 		        return a; | ||||||
|  | 		    } | ||||||
|  | 		    if (a.slice && a.map) { | ||||||
|  | 		        return (a as any[]).map(elem => this.convertValues(elem, classs)); | ||||||
|  | 		    } else if ("object" === typeof a) { | ||||||
|  | 		        if (asMap) { | ||||||
|  | 		            for (const key of Object.keys(a)) { | ||||||
|  | 		                a[key] = new classs(a[key]); | ||||||
|  | 		            } | ||||||
|  | 		            return a; | ||||||
|  | 		        } | ||||||
|  | 		        return new classs(a); | ||||||
|  | 		    } | ||||||
|  | 		    return a; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.go
									
									
									
									
									
								
							| @@ -61,7 +61,7 @@ func main() { | |||||||
|  |  | ||||||
| 	// Create application with options | 	// Create application with options | ||||||
| 	err = wails.Run(&options.App{ | 	err = wails.Run(&options.App{ | ||||||
| 		Title:  "bill-manager-w", | 		Title:  "bill-manager", | ||||||
| 		Width:  1024, | 		Width:  1024, | ||||||
| 		Height: 768, | 		Height: 768, | ||||||
| 		AssetServer: &assetserver.Options{ | 		AssetServer: &assetserver.Options{ | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ package main | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"log" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -14,6 +15,7 @@ const paymentColumns = "id, billid, monthFor, paymentDate" | |||||||
| const billColumns = "id, name" | const billColumns = "id, name" | ||||||
|  |  | ||||||
| func (s *BillService) GetPaymentsForDate(date time.Time) ([]Payment, error) { | func (s *BillService) GetPaymentsForDate(date time.Time) ([]Payment, error) { | ||||||
|  | 	log.Printf("GetPaymentsForDate for %v", date) | ||||||
| 	res := []Payment{} | 	res := []Payment{} | ||||||
| 	if s == nil { | 	if s == nil { | ||||||
| 		return res, fmt.Errorf("calling GetPaymentsFor on nil BillService") | 		return res, fmt.Errorf("calling GetPaymentsFor on nil BillService") | ||||||
| @@ -45,6 +47,7 @@ WHERE monthFor = date(strftime('%%Y-%%m-01', ?)); | |||||||
| } | } | ||||||
|  |  | ||||||
| func (s *BillService) GetPaymentForBillAndDate(billid int64, date time.Time) (Payment, error) { | func (s *BillService) GetPaymentForBillAndDate(billid int64, date time.Time) (Payment, error) { | ||||||
|  | 	log.Printf("GetPaymentForBillAndDate for %d and %s", billid, date) | ||||||
| 	res := Payment{} | 	res := Payment{} | ||||||
| 	if s == nil { | 	if s == nil { | ||||||
| 		return res, fmt.Errorf("calling GetPaymentsFor on nil BillService") | 		return res, fmt.Errorf("calling GetPaymentsFor on nil BillService") | ||||||
| @@ -68,6 +71,7 @@ WHERE billid = ? AND monthFor = date(strftime('%%Y-%%m-01', ?)); | |||||||
| } | } | ||||||
|  |  | ||||||
| func (s *BillService) GetAllBills() ([]Bill, error) { | func (s *BillService) GetAllBills() ([]Bill, error) { | ||||||
|  | 	log.Printf("GetAllBills") | ||||||
| 	res := []Bill{} | 	res := []Bill{} | ||||||
| 	if s == nil { | 	if s == nil { | ||||||
| 		return res, fmt.Errorf("calling GetAllBills on nil BillService") | 		return res, fmt.Errorf("calling GetAllBills on nil BillService") | ||||||
| @@ -100,6 +104,7 @@ func (s *BillService) GetAllBills() ([]Bill, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (s *BillService) MarkPaid(billid int64, monthFor time.Time, when time.Time) (Payment, error) { | func (s *BillService) MarkPaid(billid int64, monthFor time.Time, when time.Time) (Payment, error) { | ||||||
|  | 	log.Printf("MarkPaid for %d, %v and %v", billid, monthFor, when) | ||||||
| 	res := Payment{} | 	res := Payment{} | ||||||
| 	if s == nil { | 	if s == nil { | ||||||
| 		return res, fmt.Errorf("calling MarkPaid on nil BillService") | 		return res, fmt.Errorf("calling MarkPaid on nil BillService") | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								types.go
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								types.go
									
									
									
									
									
								
							| @@ -4,29 +4,29 @@ import "time" | |||||||
|  |  | ||||||
| type ( | type ( | ||||||
| 	Bill struct { | 	Bill struct { | ||||||
| 		Id   int64 | 		Id   int64  `json:"id"` | ||||||
| 		Name string | 		Name string `json:"name"` | ||||||
| 	} | 	} | ||||||
| 	Payment struct { | 	Payment struct { | ||||||
| 		Id          int64 | 		Id          int64     `json:"id"` | ||||||
| 		BillId      int64 | 		BillId      int64     `json:"billId"` | ||||||
| 		MonthFor    time.Time | 		MonthFor    time.Time `json:"monthFor" time_format:"2006-01-02"` | ||||||
| 		PaymentDate time.Time | 		PaymentDate time.Time `json:"paymentDate" time_format:"2006-01-02T15:04:05"` | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	WailsBills struct { | 	WailsBills struct { | ||||||
| 		Data    []Bill | 		Data    []Bill `json:"data"` | ||||||
| 		Success bool | 		Success bool   `json:"success"` | ||||||
| 		Error   string | 		Error   string `json:"error"` | ||||||
| 	} | 	} | ||||||
| 	WailsPayments struct { | 	WailsPayments struct { | ||||||
| 		Data    []Payment | 		Data    []Payment `json:"data"` | ||||||
| 		Success bool | 		Success bool      `json:"success"` | ||||||
| 		Error   string | 		Error   string    `json:"error"` | ||||||
| 	} | 	} | ||||||
| 	WailsPayment struct { | 	WailsPayment struct { | ||||||
| 		Data    Payment | 		Data    Payment `json:"data"` | ||||||
| 		Success bool | 		Success bool    `json:"success"` | ||||||
| 		Error   string | 		Error   string  `json:"error"` | ||||||
| 	} | 	} | ||||||
| ) | ) | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| { | { | ||||||
|   "$schema": "https://wails.io/schemas/config.v2.json", |   "$schema": "https://wails.io/schemas/config.v2.json", | ||||||
|   "name": "wails-template", |   "name": "bill-manager", | ||||||
|   "outputfilename": "wails-template", |   "outputfilename": "bill-manager", | ||||||
|   "frontend:install": "pnpm install", |   "frontend:install": "pnpm install", | ||||||
|   "frontend:build": "pnpm build", |   "frontend:build": "pnpm build", | ||||||
|   "frontend:dev:watcher": "pnpm dev", |   "frontend:dev:watcher": "pnpm dev", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user