chore: some refactor and semplification

This commit is contained in:
2025-01-19 11:25:31 +01:00
parent d473941773
commit 3bd243778c
8 changed files with 50 additions and 41 deletions

View File

@@ -17,19 +17,19 @@ A personal expenses and day log tracking API that works with Siri Shortcuts. Usi
#### Add an Expense #### Add an Expense
``` ```
add --desc "description" --cost amount --cat category add -desc "description" -cost amount -cat category
``` ```
Example: `add --desc "Weekly groceries" --cost 87.50 --cat groceries` Example: `add -desc "Weekly groceries" -cost 87.50 -cat groceries`
#### Update an Expense #### Update an Expense
``` ```
update expenseId --desc "new description" --cost newAmount --cat newCategory update expenseId -desc "new description" -cost newAmount -cat newCategory
``` ```
All flags are optional - only include what you want to change. All flags are optional - only include what you want to change.
Example: `update abc123 --cost 92.30 --cat groceries` Example: `update abc123 -cost 92.30 -cat groceries`
#### Delete an Expense #### Delete an Expense
@@ -42,9 +42,11 @@ Example: `delete abc123`
#### Generate Report #### Generate Report
``` ```
report --dateFrom "2025-01-01" --dateTo "2025-01-31" --export true report -from dateFrom -to dateTo -export boolean
``` ```
Example: `report -from "2025-01-01" -to "2025-01-31" -export true`
Generates and emails an expense report for the specified period. The report includes: Generates and emails an expense report for the specified period. The report includes:
- Total expenses for the period - Total expenses for the period
@@ -56,9 +58,11 @@ The `export` flag is optional - when set to true, a JSON file with the raw data
### Day Log ### Day Log
``` ```
daylog --text "Meeting notes or daily summary" --date "2024-01-18" daylog -text "text" -date "date"
``` ```
Example: `daylog -text "Meeting notes or daily summary" -date "2024-01-18"`
Adds a log entry for a specific day. The date parameter is optional and defaults to the current date. Adds a log entry for a specific day. The date parameter is optional and defaults to the current date.
Logs are stored with UTC midnight timestamps for consistent date handling Logs are stored with UTC midnight timestamps for consistent date handling
@@ -194,7 +198,7 @@ Example shortcut configuration:
{ {
"command": "expense", "command": "expense",
"parameters": { "parameters": {
"instruction": "add --desc \"Coffee\" --cost 3.50 --cat food" "instruction": "add -desc \"Coffee\" -cost 3.50 -cat food"
}, },
"apiKey": "your_api_key_here" "apiKey": "your_api_key_here"
} }

View File

@@ -2,8 +2,7 @@ import type { Metadata } from 'next';
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'DiaryWhisper', title: 'DiaryWhisper',
description: description: 'Siri-enabled diary tracker for expenses and day logs'
'Siri-enabled diary tracker for expenses and day logs'
}; };
export default function RootLayout({ export default function RootLayout({

View File

@@ -4,36 +4,37 @@ import React from 'react';
export default function Home() { export default function Home() {
const commands = [ const commands = [
'expense add --desc "Coffee" --cost 3.50 --cat "Food"', 'expense add -desc "Coffee" -cost 3.50 -cat "Food"',
'expense report --dateFrom "2024-01-01" --dateTo "2024-01-31"', 'expense report -from "2024-01-01" -to "2024-01-31"',
'expense daylog --text "Added team lunch" --date "2024-01-18"' 'expense daylog -text "Added team lunch" -date "2024-01-18"'
]; ];
return ( return (
<> <>
<div className="container"> <div className='container'>
<div className="header"> <div className='header'>
<h1>DiaryWhisper v1.0.0</h1> <h1>DiaryWhisper v1.0.0</h1>
<p>Your expenses and day logs tracked via Siri Shortcuts</p> <p>Your expenses and day logs tracked via Siri Shortcuts</p>
</div> </div>
<div className="terminal"> <div className='terminal'>
<div>Loading system components...</div> <div>Loading system components...</div>
<div>Initializing expense database... OK</div> <div>Initializing expense database... OK</div>
<div>Starting expense tracking daemon... OK</div> <div>Starting expense tracking daemon... OK</div>
<div>System ready_</div> <div>System ready_</div>
</div> </div>
<div className="commands"> <div className='commands'>
<h2>Available Commands:</h2> <h2>Available Commands:</h2>
{commands.map((cmd, i) => ( {commands.map((cmd, i) => (
<div key={i} className="command"> <div key={i} className='command'>
<span>$ </span>{cmd} <span>$ </span>
{cmd}
</div> </div>
))} ))}
</div> </div>
<div className="status"> <div className='status'>
<span>Status: OPERATIONAL</span> <span>Status: OPERATIONAL</span>
<span>Database: CONNECTED</span> <span>Database: CONNECTED</span>
<span>Last Backup: 2024-01-18 14:30 UTC</span> <span>Last Backup: 2024-01-18 14:30 UTC</span>

View File

@@ -1,9 +1,13 @@
import { ExpenseType, ShortcutsResponse } from '../types'; import { ExpenseType, ShortcutsResponse } from '@utils/types';
import { CommandParser, diaryCommands } from './commandParser'; import { CommandParser, diaryCommands } from './helpers/commandParser';
import { Category, Expense } from '@prisma/client'; import { Category, Expense } from '@prisma/client';
import { ExpenseReporter } from './report'; import { ExpenseReporter } from './report';
import { createExpense, deleteExpense, updateExpense } from '@utils/expense'; import {
import { processDayLog } from '@utils/commands/dayLog'; createExpense,
deleteExpense,
updateExpense
} from '@utils/commands/helpers/expense';
import { processDayLog } from '@utils/commands/helpers/dayLog';
const formatResponse = (expense: Expense & { category: Category }) => ({ const formatResponse = (expense: Expense & { category: Category }) => ({
id: expense.id, id: expense.id,
@@ -97,8 +101,8 @@ export async function diaryCommand(
case 'report': { case 'report': {
try { try {
const reporter = new ExpenseReporter(); const reporter = new ExpenseReporter();
const from = parsedCommand.flags.dateFrom as Date; const from = parsedCommand.flags.from as Date;
const to = parsedCommand.flags.dateTo as Date; const to = parsedCommand.flags.to as Date;
const includeJson = (parsedCommand.flags.export as boolean) || false; const includeJson = (parsedCommand.flags.export as boolean) || false;
await reporter.sendReport(from, to, includeJson); await reporter.sendReport(from, to, includeJson);

View File

@@ -42,11 +42,11 @@ export class CommandParser {
while (currentIndex < parts.length) { while (currentIndex < parts.length) {
const flag = parts[currentIndex]; const flag = parts[currentIndex];
if (!flag.startsWith('--')) { if (!flag.startsWith('-')) {
throw new Error(`Invalid flag format at: ${flag}`); throw new Error(`Invalid flag format at: ${flag}`);
} }
const flagName = flag.slice(2); const flagName = flag.slice(1);
const flagDef = definition.flags.find( const flagDef = definition.flags.find(
f => f.name === flagName || f.alias === flagName f => f.name === flagName || f.alias === flagName
); );
@@ -133,8 +133,8 @@ export const diaryCommands: CommandDefinition[] = [
{ {
name: 'report', name: 'report',
flags: [ flags: [
{ name: 'dateFrom', type: 'date', required: true }, { name: 'from', type: 'date', required: true },
{ name: 'dateTo', type: 'date', required: true }, { name: 'to', type: 'date', required: true },
{ name: 'export', type: 'boolean', required: false } { name: 'export', type: 'boolean', required: false }
] ]
}, },

View File

@@ -60,7 +60,8 @@ export async function processDayLog(
console.error('Error processing daylog:', error); console.error('Error processing daylog:', error);
return { return {
success: false, success: false,
message: error instanceof Error ? error.message : 'Failed to process daylog' message:
error instanceof Error ? error.message : 'Failed to process daylog'
}; };
} }
} }

View File

@@ -1,5 +1,5 @@
import prisma from '@prisma/prisma'; import prisma from '@prisma/prisma';
import { ExpenseType } from './types'; import { ExpenseType } from '@utils/types';
const createOrGetCategory = async (name: string) => { const createOrGetCategory = async (name: string) => {
const category = await prisma.category.upsert({ const category = await prisma.category.upsert({

View File

@@ -1,7 +1,7 @@
import { ShortcutsResponse } from './types'; import { ShortcutsResponse } from './types';
import { pingCommand } from './commands/ping'; import { pingCommand } from './commands/ping';
import { diaryCommand } from './commands/diary'; import { diaryCommand } from './commands/diary';
import { CommandParser, diaryCommands } from './commands/commandParser'; import { CommandParser, diaryCommands } from './commands/helpers/commandParser';
type CommandHandler = ( type CommandHandler = (
parameters?: Record<string, string> parameters?: Record<string, string>