feat: expenses, report and day log commands
This commit is contained in:
50
app/api/command/route.ts
Normal file
50
app/api/command/route.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { ShortcutsHandler } from '@utils/handler';
|
||||
import { RequestSchema } from '@utils/types';
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const body = await req.json();
|
||||
|
||||
const result = RequestSchema.safeParse(body);
|
||||
if (!result.success) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
message: 'Invalid request format.',
|
||||
errors: result.error.errors
|
||||
},
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const shortcutsHandler = new ShortcutsHandler();
|
||||
const isValid = shortcutsHandler.validateRequest(result.data);
|
||||
|
||||
if (!isValid) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
message: 'Unauthorized.'
|
||||
},
|
||||
{ status: 401 }
|
||||
);
|
||||
}
|
||||
|
||||
const response = await shortcutsHandler.processCommand(
|
||||
result.data.command,
|
||||
result.data.parameters
|
||||
);
|
||||
|
||||
return NextResponse.json(response);
|
||||
} catch (error) {
|
||||
console.error('Error processing shortcuts request:', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
message: 'An error occurred while processing your request.'
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
19
app/layout.tsx
Normal file
19
app/layout.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'DiaryWhisper',
|
||||
description:
|
||||
'Siri-enabled diary tracker for expenses and day logs'
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html lang='en'>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
113
app/page.tsx
Normal file
113
app/page.tsx
Normal file
@@ -0,0 +1,113 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export default function Home() {
|
||||
const commands = [
|
||||
'expense add --desc "Coffee" --cost 3.50 --cat "Food"',
|
||||
'expense report --dateFrom "2024-01-01" --dateTo "2024-01-31"',
|
||||
'expense daylog --text "Added team lunch" --date "2024-01-18"'
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="container">
|
||||
<div className="header">
|
||||
<h1>DiaryWhisper v1.0.0</h1>
|
||||
<p>Your expenses and day logs tracked via Siri Shortcuts</p>
|
||||
</div>
|
||||
|
||||
<div className="terminal">
|
||||
<div>Loading system components...</div>
|
||||
<div>Initializing expense database... OK</div>
|
||||
<div>Starting expense tracking daemon... OK</div>
|
||||
<div>System ready_</div>
|
||||
</div>
|
||||
|
||||
<div className="commands">
|
||||
<h2>Available Commands:</h2>
|
||||
{commands.map((cmd, i) => (
|
||||
<div key={i} className="command">
|
||||
<span>$ </span>{cmd}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="status">
|
||||
<span>Status: OPERATIONAL</span>
|
||||
<span>Database: CONNECTED</span>
|
||||
<span>Last Backup: 2024-01-18 14:30 UTC</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style jsx global>{`
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-height: 100vh;
|
||||
background: #0a0a0a;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<style jsx>{`
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
padding: 2rem;
|
||||
background: #0a0a0a;
|
||||
color: #00ff00;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.terminal {
|
||||
background: #000;
|
||||
border: 1px solid #00ff00;
|
||||
padding: 1rem;
|
||||
margin: 2rem 0;
|
||||
max-width: 800px;
|
||||
margin: 2rem auto;
|
||||
}
|
||||
|
||||
.terminal div {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.commands {
|
||||
max-width: 800px;
|
||||
margin: 2rem auto;
|
||||
}
|
||||
|
||||
.command {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.status {
|
||||
max-width: 800px;
|
||||
margin: 2rem auto;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid #00ff00;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.status {
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</>
|
||||
);
|
||||
}
|
||||
12
app/robots.ts
Normal file
12
app/robots.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { MetadataRoute } from 'next';
|
||||
|
||||
export default function robots(): MetadataRoute.Robots {
|
||||
return {
|
||||
rules: [
|
||||
{
|
||||
userAgent: '*',
|
||||
disallow: '/'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user