chore: some refactor and semplification
This commit is contained in:
18
README.md
18
README.md
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
23
app/page.tsx
23
app/page.tsx
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -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'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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({
|
||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user