mirror of
https://github.com/marcogll/TaxHacker_s23.git
synced 2026-01-13 21:35:19 +00:00
feat: add more colors to cards
This commit is contained in:
@@ -11,8 +11,8 @@ import { getFilesByTransactionId } from "@/models/files"
|
|||||||
import { getProjects } from "@/models/projects"
|
import { getProjects } from "@/models/projects"
|
||||||
import { getSettings } from "@/models/settings"
|
import { getSettings } from "@/models/settings"
|
||||||
import { getTransactionById } from "@/models/transactions"
|
import { getTransactionById } from "@/models/transactions"
|
||||||
import { notFound } from "next/navigation"
|
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
export default async function TransactionPage({ params }: { params: Promise<{ transactionId: string }> }) {
|
export default async function TransactionPage({ params }: { params: Promise<{ transactionId: string }> }) {
|
||||||
const { transactionId } = await params
|
const { transactionId } = await params
|
||||||
@@ -32,7 +32,7 @@ export default async function TransactionPage({ params }: { params: Promise<{ tr
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-wrap flex-row items-start justify-center gap-4 max-w-6xl">
|
<div className="flex flex-wrap flex-row items-start justify-center gap-4 max-w-6xl">
|
||||||
<Card className="w-full flex-1 flex flex-col flex-wrap justify-center items-start overflow-hidden">
|
<Card className="w-full flex-1 flex flex-col flex-wrap justify-center items-start overflow-hidden bg-gradient-to-br from-violet-50/80 via-indigo-50/80 to-white border-violet-200/60">
|
||||||
{incompleteFields.length > 0 && (
|
{incompleteFields.length > 0 && (
|
||||||
<div className="w-full flex flex-col gap-1 rounded-md bg-yellow-50 p-5">
|
<div className="w-full flex flex-col gap-1 rounded-md bg-yellow-50 p-5">
|
||||||
<span>
|
<span>
|
||||||
@@ -47,7 +47,7 @@ export default async function TransactionPage({ params }: { params: Promise<{ tr
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="w-full p-5 bg-accent">
|
<div className="w-full p-5">
|
||||||
<TransactionEditForm
|
<TransactionEditForm
|
||||||
transaction={transaction}
|
transaction={transaction}
|
||||||
categories={categories}
|
categories={categories}
|
||||||
|
|||||||
@@ -38,29 +38,32 @@ export default async function UnsortedPage() {
|
|||||||
{files.length > 1 && <AnalyzeAllButton />}
|
{files.length > 1 && <AnalyzeAllButton />}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{config.selfHosted.isEnabled && !settings.openai_api_key && !settings.google_api_key && !settings.mistral_api_key && (
|
{config.selfHosted.isEnabled &&
|
||||||
<Alert>
|
!settings.openai_api_key &&
|
||||||
<Settings className="h-4 w-4 mt-2" />
|
!settings.google_api_key &&
|
||||||
<div className="flex flex-row justify-between pt-2">
|
!settings.mistral_api_key && (
|
||||||
<div className="flex flex-col">
|
<Alert>
|
||||||
<AlertTitle>LLM provider API Key is required for analyzing files</AlertTitle>
|
<Settings className="h-4 w-4 mt-2" />
|
||||||
<AlertDescription>
|
<div className="flex flex-row justify-between pt-2">
|
||||||
Please set your LLM provider API key in the settings to use the analyze form.
|
<div className="flex flex-col">
|
||||||
</AlertDescription>
|
<AlertTitle>LLM provider API Key is required for analyzing files</AlertTitle>
|
||||||
|
<AlertDescription>
|
||||||
|
Please set your LLM provider API key in the settings to use the analyze form.
|
||||||
|
</AlertDescription>
|
||||||
|
</div>
|
||||||
|
<Link href="/settings/llm">
|
||||||
|
<Button>Go to Settings</Button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<Link href="/settings/llm">
|
</Alert>
|
||||||
<Button>Go to Settings</Button>
|
)}
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<main className="flex flex-col gap-5">
|
<main className="flex flex-col gap-5">
|
||||||
{files.map((file) => (
|
{files.map((file) => (
|
||||||
<Card
|
<Card
|
||||||
key={file.id}
|
key={file.id}
|
||||||
id={file.id}
|
id={file.id}
|
||||||
className="flex flex-row flex-wrap md:flex-nowrap justify-center items-start gap-5 p-5 bg-accent"
|
className="flex flex-row flex-wrap md:flex-nowrap justify-center items-start gap-5 p-5 bg-gradient-to-br from-violet-50/80 via-indigo-50/80 to-white border-violet-200/60 rounded-2xl"
|
||||||
>
|
>
|
||||||
<div className="w-full max-w-[500px]">
|
<div className="w-full max-w-[500px]">
|
||||||
<Card>
|
<Card>
|
||||||
|
|||||||
@@ -6,23 +6,32 @@ import Link from "next/link"
|
|||||||
|
|
||||||
export default function LandingPage() {
|
export default function LandingPage() {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen flex flex-col bg-[#FAFAFA]">
|
<div className="min-h-screen flex flex-col bg-gradient-to-br from-pink-50 via-purple-50 to-indigo-50">
|
||||||
<header className="py-6 px-4 md:px-8 bg-white/80 backdrop-blur-md shadow-sm fixed w-full z-10">
|
<header className="py-6 px-4 md:px-8 bg-white/90 backdrop-blur-xl shadow-lg border-b border-gradient-to-r from-pink-200 to-indigo-200 fixed w-full z-50">
|
||||||
<div className="max-w-7xl mx-auto flex justify-between items-center">
|
<div className="max-w-7xl mx-auto flex justify-between items-center">
|
||||||
<Link href="/" className="flex items-center gap-2">
|
<Link href="/" className="flex items-center gap-2 group">
|
||||||
<Image src="/logo/256.png" alt="Logo" width={32} height={32} className="h-8" />
|
<div className="relative">
|
||||||
|
<Image
|
||||||
|
src="/logo/256.png"
|
||||||
|
alt="Logo"
|
||||||
|
width={32}
|
||||||
|
height={32}
|
||||||
|
className="h-8 group-hover:scale-110 transition-transform duration-300"
|
||||||
|
/>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-r from-pink-600 to-indigo-600 rounded-full opacity-20 blur-md group-hover:opacity-40 transition-opacity duration-300" />
|
||||||
|
</div>
|
||||||
<ColoredText className="text-2xl font-bold">TaxHacker</ColoredText>
|
<ColoredText className="text-2xl font-bold">TaxHacker</ColoredText>
|
||||||
</Link>
|
</Link>
|
||||||
<div className="flex gap-1 md:gap-4 text-xs md:text-sm">
|
<div className="flex gap-1 md:gap-4 text-xs md:text-sm">
|
||||||
<Link
|
<Link
|
||||||
href="/enter"
|
href="/enter"
|
||||||
className="font-medium px-4 py-2 rounded-full border border-gray-200 hover:bg-gray-50 transition-all"
|
className="font-medium px-4 py-2 rounded-full border-2 border-gradient-to-r from-pink-300 to-indigo-300 hover:from-pink-400 hover:to-indigo-400 bg-white/80 hover:bg-white transition-all duration-300 hover:scale-105"
|
||||||
>
|
>
|
||||||
Log In
|
Log In
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href="/cloud"
|
href="/cloud"
|
||||||
className="font-medium bg-gradient-to-r from-blue-600 to-indigo-600 text-white px-4 py-2 rounded-full hover:opacity-90 transition-all"
|
className="font-medium bg-gradient-to-r from-pink-600 to-indigo-600 text-white px-4 py-2 rounded-full hover:from-pink-700 hover:to-indigo-700 transition-all duration-300 hover:scale-105 shadow-lg hover:shadow-xl"
|
||||||
>
|
>
|
||||||
Sign Up
|
Sign Up
|
||||||
</Link>
|
</Link>
|
||||||
@@ -31,35 +40,40 @@ export default function LandingPage() {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="pt-32 pb-16 px-8">
|
<section className="pt-32 pb-16 px-8 relative overflow-hidden">
|
||||||
<div className="max-w-7xl mx-auto">
|
{/* Background decoration */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-br from-pink-100/50 via-purple-100/30 to-indigo-100/50" />
|
||||||
|
<div className="absolute top-20 left-10 w-72 h-72 bg-gradient-to-r from-pink-400 to-indigo-400 rounded-full opacity-10 blur-3xl animate-pulse" />
|
||||||
|
<div className="absolute bottom-20 right-10 w-96 h-96 bg-gradient-to-r from-indigo-400 to-pink-400 rounded-full opacity-10 blur-3xl animate-pulse" />
|
||||||
|
|
||||||
|
<div className="max-w-7xl mx-auto relative z-10">
|
||||||
<div className="text-center mb-12">
|
<div className="text-center mb-12">
|
||||||
<div className="inline-block px-4 py-2 rounded-full bg-purple-50 text-purple-600 text-sm font-medium mb-6">
|
<div className="inline-block px-6 py-3 rounded-full bg-gradient-to-r from-pink-600 to-indigo-600 text-white text-sm font-medium mb-6 shadow-lg hover:shadow-xl transition-all duration-300 hover:scale-105">
|
||||||
🚀 Under Active Development
|
🚀 Under Active Development
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-5xl font-bold tracking-tight sm:text-6xl mb-6 bg-gradient-to-r from-gray-900 to-gray-600 bg-clip-text text-transparent pb-2">
|
<h1 className="text-5xl font-bold tracking-tight sm:text-6xl mb-6 bg-gradient-to-r from-gray-900 via-pink-700 to-indigo-700 bg-clip-text text-transparent pb-2">
|
||||||
Let AI finally care about your taxes, scan your receipts and analyze your expenses
|
Let AI finally care about your taxes, scan your receipts and analyze your expenses
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-xl text-gray-600 mb-8 max-w-2xl mx-auto">
|
<p className="text-xl text-gray-700 mb-8 max-w-2xl mx-auto font-medium">
|
||||||
A self-hosted accounting app crafted with love for freelancers and small businesses
|
A self-hosted accounting app crafted with love for freelancers and small businesses
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gap-4 justify-center text-sm md:text-lg">
|
<div className="flex gap-4 justify-center text-sm md:text-lg">
|
||||||
<Link
|
<Link
|
||||||
href="#start"
|
href="#start"
|
||||||
className="px-8 py-3 bg-gradient-to-r from-blue-600 to-indigo-600 text-white font-medium rounded-full hover:opacity-90 transition-all shadow-lg shadow-blue-500/20"
|
className="px-8 py-4 bg-gradient-to-r from-pink-600 to-indigo-600 text-white font-bold rounded-full hover:from-pink-700 hover:to-indigo-700 transition-all duration-300 shadow-xl hover:shadow-2xl hover:scale-110 border-2 border-white/20"
|
||||||
>
|
>
|
||||||
Get Started
|
Get Started ✨
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href="mailto:me@vas3k.ru"
|
href="mailto:me@vas3k.ru"
|
||||||
className="px-8 py-3 border border-gray-200 text-gray-700 font-medium rounded-full hover:bg-gray-50 transition-all"
|
className="px-8 py-4 border-2 border-gradient-to-r from-pink-300 to-indigo-300 text-gray-800 font-bold rounded-full hover:bg-gradient-to-r hover:from-pink-50 hover:to-indigo-50 transition-all duration-300 hover:scale-105 bg-white/80"
|
||||||
>
|
>
|
||||||
Contact Us
|
Contact Us 💌
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative aspect-auto rounded-2xl overflow-hidden shadow-2xl ring-8 ring-gray-100 hover:scale-105 transition-all duration-300">
|
<div className="relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-pink-200 to-indigo-200 hover:scale-105 transition-all duration-500 group">
|
||||||
<div className="absolute inset-0 bg-gradient-to-b from-blue-500/5 to-transparent z-10" />
|
<div className="absolute inset-0 bg-gradient-to-b from-pink-500/10 via-purple-500/10 to-indigo-500/10 z-10 group-hover:from-pink-500/20 group-hover:to-indigo-500/20 transition-all duration-500" />
|
||||||
<video className="w-full h-auto" autoPlay loop muted playsInline poster="/landing/title.webp">
|
<video className="w-full h-auto" autoPlay loop muted playsInline poster="/landing/title.webp">
|
||||||
<source src="/landing/video.mp4" type="video/mp4" />
|
<source src="/landing/video.mp4" type="video/mp4" />
|
||||||
<Image src="/landing/title.webp" alt="TaxHacker" width={1980} height={1224} priority />
|
<Image src="/landing/title.webp" alt="TaxHacker" width={1980} height={1224} priority />
|
||||||
@@ -69,133 +83,179 @@ export default function LandingPage() {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Features Section */}
|
{/* Features Section */}
|
||||||
<section className="py-20 px-8">
|
<section className="py-20 px-8 relative">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="absolute inset-0 bg-gradient-to-b from-white/50 to-indigo-50/50" />
|
||||||
|
<div className="max-w-7xl mx-auto relative z-10">
|
||||||
<div className="text-center mb-16">
|
<div className="text-center mb-16">
|
||||||
<h2 className="flex flex-col gap-3 mb-4 bg-gradient-to-r from-gray-900 to-gray-600 bg-clip-text text-transparent">
|
<h2 className="flex flex-col gap-3 mb-4">
|
||||||
<span className="text-6xl font-semibold text-muted-foreground">F∗ck Taxes</span>
|
<span className="text-6xl font-bold bg-gradient-to-r from-pink-600 to-indigo-600 bg-clip-text text-transparent">
|
||||||
<span className="text-4xl font-bold">TaxHacker can save you time, money and nerves</span>
|
F∗ck Taxes
|
||||||
|
</span>
|
||||||
|
<span className="text-4xl font-bold bg-gradient-to-r from-gray-900 to-gray-600 bg-clip-text text-transparent">
|
||||||
|
TaxHacker can save you time, money and nerves
|
||||||
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* AI Scanner Feature */}
|
{/* AI Scanner Feature */}
|
||||||
<div className="flex flex-wrap items-center gap-12 mb-20 bg-white p-8 rounded-2xl shadow-sm ring-1 ring-gray-100">
|
<div className="flex flex-wrap items-center gap-12 mb-20 bg-gradient-to-br from-white via-pink-50/30 to-indigo-50/30 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-pink-200 to-indigo-200 hover:shadow-2xl transition-all duration-500 group">
|
||||||
<div className="flex-1 min-w-60">
|
<div className="flex-1 min-w-60">
|
||||||
<div className="inline-block px-3 py-1 rounded-full bg-blue-50 text-blue-600 text-sm font-medium mb-4">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-blue-500 to-indigo-600 text-white text-sm font-bold mb-4 shadow-lg">
|
||||||
LLM-Powered
|
🤖 LLM-Powered
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-semibold mb-4">Analyze photos and invoices with AI</h3>
|
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-blue-700 to-indigo-700 bg-clip-text text-transparent">
|
||||||
<ul className="space-y-3 text-gray-600">
|
Analyze photos and invoices with AI
|
||||||
|
</h3>
|
||||||
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-blue-600 mr-2">✓</span>
|
<span className="text-blue-600 mr-3 text-lg">✨</span>
|
||||||
Upload your receipts or invoices in PDF for automatic recognition
|
Upload your receipts or invoices in PDF for automatic recognition
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-blue-600 mr-2">✓</span>
|
<span className="text-blue-600 mr-3 text-lg">✨</span>
|
||||||
Extract key information like dates, amounts, and vendors
|
Extract key information like dates, amounts, and vendors
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-blue-600 mr-2">✓</span>
|
<span className="text-blue-600 mr-3 text-lg">✨</span>
|
||||||
Works with any language, format and photo quality
|
Works with any language, format and photo quality
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-blue-600 mr-2">✓</span>
|
<span className="text-blue-600 mr-3 text-lg">✨</span>
|
||||||
Automatically organize everything into a structured database
|
Automatically organize everything into a structured database
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 relative aspect-auto rounded-2xl overflow-hidden shadow-2xl ring-8 ring-gray-100 hover:scale-105 transition-all duration-300">
|
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-blue-200 to-indigo-200 hover:scale-105 transition-all duration-500">
|
||||||
<Image src="/landing/ai-scanner.webp" alt="AI Document Analyzer" width={1900} height={1524} />
|
<Image src="/landing/ai-scanner.webp" alt="AI Document Analyzer" width={1900} height={1524} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Multi-currency Feature */}
|
{/* Multi-currency Feature */}
|
||||||
<div className="flex flex-wrap items-center gap-12 mb-20 bg-white p-8 rounded-2xl shadow-sm ring-1 ring-gray-100 flex-row-reverse">
|
<div className="flex flex-wrap items-center gap-12 mb-20 bg-gradient-to-br from-white via-green-50/30 to-emerald-50/30 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-green-200 to-emerald-200 hover:shadow-2xl transition-all duration-500 group flex-row-reverse">
|
||||||
<div className="flex-1 min-w-60">
|
<div className="flex-1 min-w-60">
|
||||||
<div className="inline-block px-3 py-1 rounded-full bg-green-50 text-green-600 text-sm font-medium mb-4">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-green-500 to-emerald-600 text-white text-sm font-bold mb-4 shadow-lg">
|
||||||
Currency Converter
|
💱 Currency Converter
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-semibold mb-4">Automatically convert currencies</h3>
|
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-green-700 to-emerald-700 bg-clip-text text-transparent">
|
||||||
<ul className="space-y-3 text-gray-600">
|
Automatically convert currencies
|
||||||
|
</h3>
|
||||||
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-2">✓</span>
|
<span className="text-green-600 mr-3 text-lg">💰</span>
|
||||||
Detects foreign currencies and coverts it to yours
|
Detects foreign currencies and coverts it to yours
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-2">✓</span>
|
<span className="text-green-600 mr-3 text-lg">💰</span>
|
||||||
Historical exchange rate lookup on a date of transaction
|
Historical exchange rate lookup on a date of transaction
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-2">✓</span>
|
<span className="text-green-600 mr-3 text-lg">💰</span>
|
||||||
Support for 170+ world currencies
|
Support for 170+ world currencies
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-2">✓</span>
|
<span className="text-green-600 mr-3 text-lg">💰</span>
|
||||||
Even works with cryptocurrencies (BTC, ETH, LTC, etc.)
|
Even works with cryptocurrencies (BTC, ETH, LTC, etc.)
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 relative aspect-auto rounded-2xl overflow-hidden shadow-2xl ring-8 ring-gray-100 hover:scale-105 transition-all duration-300">
|
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-green-200 to-emerald-200 hover:scale-105 transition-all duration-500">
|
||||||
<Image src="/landing/multi-currency.webp" alt="Currency Converter" width={1400} height={1005} />
|
<Image src="/landing/multi-currency.webp" alt="Currency Converter" width={1400} height={1005} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Transaction Table Feature */}
|
{/* Transaction Table Feature */}
|
||||||
<div className="flex flex-wrap items-center gap-12 mb-20 bg-white p-8 rounded-2xl shadow-sm ring-1 ring-gray-100 flex-row-reverse">
|
<div className="flex flex-wrap items-center gap-12 mb-20 bg-gradient-to-br from-white via-pink-50/30 to-rose-50/30 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-pink-200 to-rose-200 hover:shadow-2xl transition-all duration-500 group flex-row-reverse">
|
||||||
<div className="flex-1 relative aspect-auto rounded-2xl overflow-hidden shadow-2xl ring-8 ring-gray-100 hover:scale-105 transition-all duration-300">
|
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-pink-200 to-rose-200 hover:scale-105 transition-all duration-500">
|
||||||
<Image src="/landing/transactions.webp" alt="Transactions Table" width={2000} height={1279} />
|
<Image src="/landing/transactions.webp" alt="Transactions Table" width={2000} height={1279} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-60">
|
<div className="flex-1 min-w-60">
|
||||||
<div className="inline-block px-3 py-1 rounded-full bg-pink-50 text-pink-600 text-sm font-medium mb-4">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-pink-500 to-rose-600 text-white text-sm font-bold mb-4 shadow-lg">
|
||||||
Filters
|
🔍 Filters
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-semibold mb-4">Organize expenses and income</h3>
|
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-pink-700 to-rose-700 bg-clip-text text-transparent">
|
||||||
<ul className="space-y-3 text-gray-600">
|
Organize expenses and income
|
||||||
|
</h3>
|
||||||
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-2">✓</span>
|
<span className="text-pink-600 mr-3 text-lg">📊</span>
|
||||||
Add, edit and manage your transactions
|
Add, edit and manage your transactions
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-2">✓</span>
|
<span className="text-pink-600 mr-3 text-lg">📊</span>
|
||||||
Filter by any column, category or date range
|
Filter by any column, category or date range
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-2">✓</span>
|
<span className="text-pink-600 mr-3 text-lg">📊</span>
|
||||||
Customize which columns to show in the table
|
Customize which columns to show in the table
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-2">✓</span>
|
<span className="text-pink-600 mr-3 text-lg">📊</span>
|
||||||
Import transactions from CSV
|
Import transactions from CSV
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Invoice Generator */}
|
||||||
|
<div className="flex flex-wrap items-center gap-12 mb-20 bg-gradient-to-br from-white via-purple-50/30 to-indigo-50/30 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-purple-200 to-indigo-200 hover:shadow-2xl transition-all duration-500 group">
|
||||||
|
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-purple-200 to-indigo-200 hover:scale-105 transition-all duration-500">
|
||||||
|
<Image src="/landing/invoice-generator.webp" alt="Invoice Generator" width={1800} height={1081} />
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-60">
|
||||||
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-purple-500 to-indigo-600 text-white text-sm font-bold mb-4 shadow-lg">
|
||||||
|
📋 Invoice Generator
|
||||||
|
</div>
|
||||||
|
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-purple-700 to-indigo-700 bg-clip-text text-transparent">
|
||||||
|
Create custom invoices
|
||||||
|
</h3>
|
||||||
|
<ul className="space-y-3 text-gray-700">
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
||||||
|
???
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
||||||
|
???
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
||||||
|
???
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
||||||
|
???
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Custom Fields & Categories */}
|
{/* Custom Fields & Categories */}
|
||||||
<div className="flex flex-wrap items-center gap-12 mb-20 bg-white p-8 rounded-2xl shadow-sm ring-1 ring-gray-100">
|
<div className="flex flex-wrap items-center gap-12 mb-20 bg-gradient-to-br from-white via-violet-50/30 to-purple-50/30 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-violet-200 to-purple-200 hover:shadow-2xl transition-all duration-500 group">
|
||||||
<div className="flex-1 relative aspect-auto rounded-2xl overflow-hidden shadow-2xl ring-8 ring-gray-100 hover:scale-105 transition-all duration-300">
|
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-violet-200 to-purple-200 hover:scale-105 transition-all duration-500">
|
||||||
<Image src="/landing/custom-llm.webp" alt="Custom LLM promts" width={1800} height={1081} />
|
<Image src="/landing/custom-llm.webp" alt="Custom LLM promts" width={1800} height={1081} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-60">
|
<div className="flex-1 min-w-60">
|
||||||
<div className="inline-block px-3 py-1 rounded-full bg-purple-50 text-purple-600 text-sm font-medium mb-4">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-violet-500 to-purple-600 text-white text-sm font-bold mb-4 shadow-lg">
|
||||||
Customization
|
🎨 Customization
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-semibold mb-4">Create custom LLM promts to extract anything</h3>
|
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-violet-700 to-purple-700 bg-clip-text text-transparent">
|
||||||
<ul className="space-y-3 text-gray-600">
|
Create custom LLM promts to extract anything
|
||||||
|
</h3>
|
||||||
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">✓</span>
|
<span className="text-violet-600 mr-3 text-lg">🔧</span>
|
||||||
Create custom fields and categories with your own LLM prompts
|
Create custom fields and categories with your own LLM prompts
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">✓</span>
|
<span className="text-violet-600 mr-3 text-lg">🔧</span>
|
||||||
Extract any additional information you need
|
Extract any additional information you need
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">✓</span>
|
<span className="text-violet-600 mr-3 text-lg">🔧</span>
|
||||||
Automatically categorize by project or category
|
Automatically categorize by project or category
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">✓</span>
|
<span className="text-violet-600 mr-3 text-lg">🔧</span>
|
||||||
Ask AI to assess risk level or any other criteria
|
Ask AI to assess risk level or any other criteria
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -203,30 +263,32 @@ export default function LandingPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Data Export */}
|
{/* Data Export */}
|
||||||
<div className="flex flex-wrap items-center gap-12 mb-20 bg-white p-8 rounded-2xl shadow-sm ring-1 ring-gray-100 flex-row-reverse">
|
<div className="flex flex-wrap items-center gap-12 mb-20 bg-gradient-to-br from-white via-orange-50/30 to-amber-50/30 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-orange-200 to-amber-200 hover:shadow-2xl transition-all duration-500 group flex-row-reverse">
|
||||||
<div className="flex-1 relative aspect-auto rounded-2xl overflow-hidden shadow-2xl ring-8 ring-gray-100 hover:scale-105 transition-all duration-300">
|
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-orange-200 to-amber-200 hover:scale-105 transition-all duration-500">
|
||||||
<Image src="/landing/export.webp" alt="Export" width={1200} height={1081} />
|
<Image src="/landing/export.webp" alt="Export" width={1200} height={1081} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-60">
|
<div className="flex-1 min-w-60">
|
||||||
<div className="inline-block px-3 py-1 rounded-full bg-orange-50 text-orange-600 text-sm font-medium mb-4">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-orange-500 to-amber-600 text-white text-sm font-bold mb-4 shadow-lg">
|
||||||
Export
|
📦 Export
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-semibold mb-4">Your Data — Your Rules</h3>
|
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-orange-700 to-amber-700 bg-clip-text text-transparent">
|
||||||
<ul className="space-y-3 text-gray-600">
|
Your Data — Your Rules
|
||||||
|
</h3>
|
||||||
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-orange-600 mr-2">✓</span>
|
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
||||||
Flexible filters to export your data for tax prep
|
Flexible filters to export your data for tax prep
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-orange-600 mr-2">✓</span>
|
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
||||||
Full-text search across documents
|
Full-text search across documents
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-orange-600 mr-2">✓</span>
|
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
||||||
Export to CSV with attached documents
|
Export to CSV with attached documents
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-orange-600 mr-2">✓</span>
|
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
||||||
Download full data archive to migrate to another service
|
Download full data archive to migrate to another service
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -236,83 +298,84 @@ export default function LandingPage() {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Deployment Options */}
|
{/* Deployment Options */}
|
||||||
<section id="start" className="py-20 px-8 bg-white scroll-mt-20">
|
<section
|
||||||
<div className="max-w-7xl mx-auto">
|
id="start"
|
||||||
|
className="py-20 px-8 bg-gradient-to-br from-white via-pink-50/20 to-indigo-50/20 scroll-mt-20 relative"
|
||||||
|
>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-r from-pink-100/20 to-indigo-100/20" />
|
||||||
|
<div className="max-w-7xl mx-auto relative z-10">
|
||||||
<div className="text-center mb-16">
|
<div className="text-center mb-16">
|
||||||
<h2 className="text-3xl font-bold mb-4 bg-gradient-to-r from-gray-900 to-gray-600 bg-clip-text text-transparent">
|
<h2 className="text-3xl font-bold mb-4 bg-gradient-to-r from-pink-600 to-indigo-600 bg-clip-text text-transparent">
|
||||||
Choose Your Version of TaxHacker
|
Choose Your Version of TaxHacker
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid md:grid-cols-2 gap-16">
|
<div className="grid md:grid-cols-2 gap-16">
|
||||||
{/* Self-Hosted Version */}
|
{/* Self-Hosted Version */}
|
||||||
<div className="bg-gradient-to-b from-white to-gray-50 p-8 rounded-2xl shadow-lg ring-1 ring-gray-100">
|
<div className="bg-gradient-to-br from-white via-violet-50/50 to-indigo-50/50 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-violet-200 to-indigo-200 hover:shadow-2xl transition-all duration-500 hover:scale-105 group">
|
||||||
<div className="inline-block px-3 py-1 rounded-full bg-violet-50 text-violet-600 text-sm font-medium mb-4">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-violet-500 to-indigo-600 text-white text-sm font-bold mb-4 shadow-lg">
|
||||||
Use Your Own Server
|
🏠 Use Your Own Server
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-semibold mb-4">
|
<h3 className="text-2xl font-bold mb-4">
|
||||||
<ColoredText>Self-Hosted Edition</ColoredText>
|
<ColoredText>Self-Hosted Edition</ColoredText>
|
||||||
</h3>
|
</h3>
|
||||||
<ul className="space-y-3 text-gray-600 mb-8">
|
<ul className="space-y-3 text-gray-700 mb-8">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-blue-600 mr-2">✓</span>
|
<span className="text-indigo-600 mr-3 text-lg">🆓</span>
|
||||||
Free and open source
|
Free and open source
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-blue-600 mr-2">✓</span>
|
<span className="text-indigo-600 mr-3 text-lg">🔒</span>
|
||||||
Complete control over your data
|
Complete control over your data
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-blue-600 mr-2">✓</span>
|
<span className="text-indigo-600 mr-3 text-lg">🏗️</span>
|
||||||
Use at your own infrastructure
|
Use at your own infrastructure
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-blue-600 mr-2">✓</span>
|
<span className="text-indigo-600 mr-3 text-lg">🔑</span>
|
||||||
Bring your own OpenAI keys
|
Bring your own keys (OpenAI, Gemini, Mistral, etc.)
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<Link
|
<Link
|
||||||
href="https://github.com/vas3k/TaxHacker"
|
href="https://github.com/vas3k/TaxHacker"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className="block w-full text-center px-6 py-3 bg-gradient-to-r from-blue-600 to-indigo-600 text-white font-medium rounded-full hover:opacity-90 transition-all shadow-lg shadow-blue-500/20"
|
className="block w-full text-center px-6 py-4 bg-gradient-to-r from-violet-600 to-indigo-600 text-white font-bold rounded-full hover:from-violet-700 hover:to-indigo-700 transition-all duration-300 shadow-xl hover:shadow-2xl hover:scale-110"
|
||||||
>
|
>
|
||||||
Free: Github + Docker Compose
|
Free: Github + Docker Compose 🐳
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Cloud Version */}
|
{/* Cloud Version */}
|
||||||
<div className="bg-gradient-to-b from-white to-gray-50 p-8 rounded-2xl shadow-lg ring-1 ring-gray-100">
|
<div className="bg-gradient-to-br from-white via-pink-50/50 to-purple-50/50 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-pink-200 to-purple-200 hover:shadow-2xl transition-all duration-500 hover:scale-105 group relative">
|
||||||
<div className="absolute top-4 right-4">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-pink-500 to-purple-600 text-white text-sm font-bold mb-4 shadow-lg">
|
||||||
<span className="px-3 py-1 bg-gray-100 text-gray-600 rounded-full text-sm">Coming Soon</span>
|
☁️ We Host It For You
|
||||||
</div>
|
</div>
|
||||||
<div className="inline-block px-3 py-1 rounded-full bg-purple-50 text-purple-600 text-sm font-medium mb-4">
|
<h3 className="text-2xl font-bold mb-4">
|
||||||
We Host It For You
|
|
||||||
</div>
|
|
||||||
<h3 className="text-2xl font-semibold mb-4">
|
|
||||||
<ColoredText>Cloud Edition</ColoredText>
|
<ColoredText>Cloud Edition</ColoredText>
|
||||||
</h3>
|
</h3>
|
||||||
<ul className="space-y-3 text-gray-600 mb-8">
|
<ul className="space-y-3 text-gray-700 mb-8">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-gray-400 mr-2">✓</span>
|
<span className="text-purple-600 mr-3 text-lg">🎯</span>
|
||||||
SaaS version for those who prefer less hassle
|
SaaS version for those who prefer less hassle
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-gray-400 mr-2">✓</span>
|
<span className="text-purple-600 mr-3 text-lg">🤖</span>
|
||||||
We provide AI keys and storage
|
We provide AI keys and storage
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-gray-400 mr-2">✓</span>
|
<span className="text-purple-600 mr-3 text-lg">💳</span>
|
||||||
Yearly subscription plans
|
Yearly subscription plans
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-gray-400 mr-2">✓</span>
|
<span className="text-purple-600 mr-3 text-lg">🚀</span>
|
||||||
Automatic updates and new features
|
Automatic updates and new features
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<Link
|
<Link
|
||||||
href="/cloud"
|
href="/cloud"
|
||||||
className="block w-full text-center px-6 py-3 bg-gradient-to-r from-blue-600 to-indigo-600 text-white font-medium rounded-full hover:opacity-90 transition-all shadow-lg shadow-blue-500/20"
|
className="block w-full text-center px-6 py-4 bg-gradient-to-r from-pink-600 to-purple-600 text-white font-bold rounded-full hover:from-pink-700 hover:to-purple-700 transition-all duration-300 shadow-xl hover:shadow-2xl hover:scale-110"
|
||||||
>
|
>
|
||||||
Early Access: from €35/year
|
Early Access: from €35/year 💎
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -320,105 +383,116 @@ export default function LandingPage() {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Upcoming Features */}
|
{/* Upcoming Features */}
|
||||||
<section className="py-20 px-8 bg-gradient-to-b from-white to-gray-50 mt-28">
|
<section className="py-20 px-8 bg-gradient-to-br from-indigo-50 via-purple-50 to-pink-50 mt-28 relative overflow-hidden">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="absolute top-10 left-10 w-64 h-64 bg-gradient-to-r from-pink-400 to-indigo-400 rounded-full opacity-5 blur-3xl" />
|
||||||
|
<div className="absolute bottom-10 right-10 w-80 h-80 bg-gradient-to-r from-indigo-400 to-pink-400 rounded-full opacity-5 blur-3xl" />
|
||||||
|
|
||||||
|
<div className="max-w-7xl mx-auto relative z-10">
|
||||||
<div className="text-center mb-16">
|
<div className="text-center mb-16">
|
||||||
<h2 className="text-3xl font-bold mb-4 bg-gradient-to-r from-gray-900 to-gray-600 bg-clip-text text-transparent">
|
<h2 className="text-3xl font-bold mb-4 bg-gradient-to-r from-pink-600 to-indigo-600 bg-clip-text text-transparent">
|
||||||
Upcoming Features
|
Upcoming Features
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-gray-600 max-w-2xl mx-auto">
|
<p className="text-gray-700 max-w-2xl mx-auto font-medium">
|
||||||
We're a small, indie project constantly improving. Here's what we're working on next.
|
We're a small, indie project constantly improving. Here's what we're working on next.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid md:grid-cols-2 gap-8 mb-16">
|
<div className="grid md:grid-cols-2 gap-8 mb-16">
|
||||||
{/* AI Improvements */}
|
{/* AI Improvements */}
|
||||||
<div className="bg-white p-8 rounded-2xl shadow-sm ring-1 ring-gray-100">
|
<div className="bg-gradient-to-br from-white via-purple-50/50 to-indigo-50/50 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-purple-200 to-indigo-200 hover:shadow-2xl transition-all duration-500 hover:scale-105">
|
||||||
<div className="flex items-center gap-3 mb-4">
|
<div className="flex items-center gap-3 mb-4">
|
||||||
<span className="text-2xl">🤖</span>
|
<span className="text-3xl">🤖</span>
|
||||||
<h3 className="text-xl font-semibold">Better AI Analytics & Agents</h3>
|
<h3 className="text-xl font-bold bg-gradient-to-r from-purple-700 to-indigo-700 bg-clip-text text-transparent">
|
||||||
|
Better AI Analytics & Agents
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<ul className="space-y-3 text-gray-600">
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-purple-600 mr-3 text-lg">🔮</span>
|
||||||
Income & expense insights
|
Income & expense insights
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-purple-600 mr-3 text-lg">🔮</span>
|
||||||
AI agents to automate your workflows
|
AI agents to automate your workflows
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-purple-600 mr-3 text-lg">🔮</span>
|
||||||
Recommendations for tax optimization
|
Recommendations for tax optimization
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-purple-600 mr-3 text-lg">🔮</span>
|
||||||
Custom and local LLM models
|
Custom and local LLM models
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Smart Reports */}
|
{/* Smart Reports */}
|
||||||
<div className="bg-white p-8 rounded-2xl shadow-sm ring-1 ring-gray-100">
|
<div className="bg-gradient-to-br from-white via-pink-50/50 to-rose-50/50 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-pink-200 to-rose-200 hover:shadow-2xl transition-all duration-500 hover:scale-105">
|
||||||
<div className="flex items-center gap-3 mb-4">
|
<div className="flex items-center gap-3 mb-4">
|
||||||
<span className="text-2xl">📂</span>
|
<span className="text-3xl">📊</span>
|
||||||
<h3 className="text-xl font-semibold">Smart Reports & Reminders</h3>
|
<h3 className="text-xl font-bold bg-gradient-to-r from-pink-700 to-rose-700 bg-clip-text text-transparent">
|
||||||
|
Smart Reports & Reminders
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<ul className="space-y-3 text-gray-600">
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-pink-600 mr-3 text-lg">📈</span>
|
||||||
Monthly or quarterly VAT reports
|
Monthly or quarterly VAT reports
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-pink-600 mr-3 text-lg">📈</span>
|
||||||
Tax reminders
|
Tax reminders
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-pink-600 mr-3 text-lg">📈</span>
|
||||||
Annual income & expense reports
|
Annual income & expense reports
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Transaction Review */}
|
{/* Transaction Review */}
|
||||||
<div className="bg-white p-8 rounded-2xl shadow-sm ring-1 ring-gray-100">
|
<div className="bg-gradient-to-br from-white via-green-50/50 to-emerald-50/50 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-green-200 to-emerald-200 hover:shadow-2xl transition-all duration-500 hover:scale-105">
|
||||||
<div className="flex items-center gap-3 mb-4">
|
<div className="flex items-center gap-3 mb-4">
|
||||||
<span className="text-2xl">📥</span>
|
<span className="text-3xl">📥</span>
|
||||||
<h3 className="text-xl font-semibold">Multiple Transaction Review</h3>
|
<h3 className="text-xl font-bold bg-gradient-to-r from-green-700 to-emerald-700 bg-clip-text text-transparent">
|
||||||
|
Multiple Transaction Review
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<ul className="space-y-3 text-gray-600">
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-green-600 mr-3 text-lg">💳</span>
|
||||||
Bank statement analysis
|
Bank statement analysis
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-green-600 mr-3 text-lg">💳</span>
|
||||||
Automatic data completeness checks
|
Automatic data completeness checks
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-green-600 mr-3 text-lg">💳</span>
|
||||||
Unpaid invoice tracking
|
Unpaid invoice tracking
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Custom Fields */}
|
{/* Custom Fields */}
|
||||||
<div className="bg-white p-8 rounded-2xl shadow-sm ring-1 ring-gray-100">
|
<div className="bg-gradient-to-br from-white via-orange-50/50 to-amber-50/50 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-orange-200 to-amber-200 hover:shadow-2xl transition-all duration-500 hover:scale-105">
|
||||||
<div className="flex items-center gap-3 mb-4">
|
<div className="flex items-center gap-3 mb-4">
|
||||||
<span className="text-2xl">🤯</span>
|
<span className="text-3xl">🧩</span>
|
||||||
<h3 className="text-xl font-semibold">Presets and Plugins</h3>
|
<h3 className="text-xl font-bold bg-gradient-to-r from-orange-700 to-amber-700 bg-clip-text text-transparent">
|
||||||
|
Presets and Plugins
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<ul className="space-y-3 text-gray-600">
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-orange-600 mr-3 text-lg">🌍</span>
|
||||||
Presets for different countries and industries
|
Presets for different countries and industries
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-orange-600 mr-3 text-lg">🌍</span>
|
||||||
Custom reports for various use-cases
|
Custom reports for various use-cases
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-2">→</span>
|
<span className="text-orange-600 mr-3 text-lg">🌍</span>
|
||||||
Community plugins and reports
|
Community plugins and reports
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -430,10 +504,13 @@ export default function LandingPage() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<footer className="py-8 px-8 bg-white">
|
<footer className="py-8 px-8 bg-gradient-to-r from-pink-50 to-indigo-50 border-t-2 border-gradient-to-r from-pink-200 to-indigo-200">
|
||||||
<div className="max-w-7xl mx-auto text-center text-sm text-gray-500">
|
<div className="max-w-7xl mx-auto text-center text-sm text-gray-600">
|
||||||
Made with ❤️ in Berlin by{" "}
|
Made with ❤️ in Berlin by{" "}
|
||||||
<Link href="https://github.com/vas3k" className="underline">
|
<Link
|
||||||
|
href="https://github.com/vas3k"
|
||||||
|
className="underline font-semibold hover:text-pink-600 transition-colors"
|
||||||
|
>
|
||||||
@vas3k
|
@vas3k
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
@@ -441,25 +518,37 @@ export default function LandingPage() {
|
|||||||
<section className="py-12 px-8">
|
<section className="py-12 px-8">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
<div className="flex flex-wrap gap-4 justify-center">
|
<div className="flex flex-wrap gap-4 justify-center">
|
||||||
<Link href={`mailto:${config.app.supportEmail}`} className="text-sm text-gray-600 hover:text-gray-900">
|
<Link
|
||||||
|
href={`mailto:${config.app.supportEmail}`}
|
||||||
|
className="text-sm text-gray-600 hover:text-pink-600 font-medium transition-colors"
|
||||||
|
>
|
||||||
Contact Us
|
Contact Us
|
||||||
</Link>
|
</Link>
|
||||||
<Link href="/docs/terms" className="text-sm text-gray-600 hover:text-gray-900">
|
<Link
|
||||||
|
href="/docs/terms"
|
||||||
|
className="text-sm text-gray-600 hover:text-pink-600 font-medium transition-colors"
|
||||||
|
>
|
||||||
Terms of Service
|
Terms of Service
|
||||||
</Link>
|
</Link>
|
||||||
<Link href="/docs/privacy_policy" className="text-sm text-gray-600 hover:text-gray-900">
|
<Link
|
||||||
|
href="/docs/privacy_policy"
|
||||||
|
className="text-sm text-gray-600 hover:text-pink-600 font-medium transition-colors"
|
||||||
|
>
|
||||||
Privacy Policy
|
Privacy Policy
|
||||||
</Link>
|
</Link>
|
||||||
<Link href="/docs/ai" className="text-sm text-gray-600 hover:text-gray-900">
|
<Link href="/docs/ai" className="text-sm text-gray-600 hover:text-pink-600 font-medium transition-colors">
|
||||||
AI Use Disclosure
|
AI Use Disclosure
|
||||||
</Link>
|
</Link>
|
||||||
<Link href="/docs/cookie" className="text-sm text-gray-600 hover:text-gray-900">
|
<Link
|
||||||
|
href="/docs/cookie"
|
||||||
|
className="text-sm text-gray-600 hover:text-pink-600 font-medium transition-colors"
|
||||||
|
>
|
||||||
Cookie Policy
|
Cookie Policy
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href="https://github.com/vas3k/TaxHacker"
|
href="https://github.com/vas3k/TaxHacker"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className="text-sm text-gray-600 hover:text-gray-900"
|
className="text-sm text-gray-600 hover:text-pink-600 font-medium transition-colors"
|
||||||
>
|
>
|
||||||
Source Code
|
Source Code
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -16,75 +16,83 @@ export function ProjectsWidget({
|
|||||||
return (
|
return (
|
||||||
<div className="grid gap-4 md:grid-cols-2">
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
{projects.map((project) => (
|
{projects.map((project) => (
|
||||||
<Card key={project.code}>
|
<Link key={project.code} href={`/transactions?projectCode=${project.code}`}>
|
||||||
<CardHeader>
|
<Card className="bg-gradient-to-tr from-white via-slate-50/40 to-purple-50/30 border-slate-200/60 hover:shadow-xl transition-all duration-500 hover:scale-[1.01] group cursor-pointer">
|
||||||
<CardTitle>
|
<CardHeader className="group-hover:translate-y-[-2px] transition-transform duration-300">
|
||||||
<Link href={`/transactions?projectCode=${project.code}`}>
|
<CardTitle>
|
||||||
<Badge className="text-lg" style={{ backgroundColor: project.color }}>
|
<Badge
|
||||||
|
className="text-lg shadow-md hover:shadow-lg transition-all duration-300"
|
||||||
|
style={{ backgroundColor: project.color }}
|
||||||
|
>
|
||||||
{project.name}
|
{project.name}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Link>
|
</CardTitle>
|
||||||
</CardTitle>
|
</CardHeader>
|
||||||
</CardHeader>
|
<CardContent className="group-hover:translate-y-[-1px] transition-transform duration-300">
|
||||||
<CardContent>
|
<div className="flex flex-wrap gap-4 justify-between items-center">
|
||||||
<div className="flex flex-wrap gap-4 justify-between items-center">
|
<div className="bg-gradient-to-br from-green-50/80 to-emerald-50/60 p-3 rounded-xl border border-green-100/50">
|
||||||
<div>
|
<div className="text-sm font-medium text-muted-foreground">Income</div>
|
||||||
<div className="text-sm font-medium text-muted-foreground">Income</div>
|
<div className="text-2xl font-bold text-green-500">
|
||||||
<div className="text-2xl font-bold text-green-500">
|
{Object.entries(statsPerProject[project.code]?.totalIncomePerCurrency).map(([currency, total]) => (
|
||||||
{Object.entries(statsPerProject[project.code]?.totalIncomePerCurrency).map(([currency, total]) => (
|
<div
|
||||||
<div
|
key={currency}
|
||||||
key={currency}
|
className="flex flex-col gap-2 font-bold text-green-500 text-base first:text-2xl"
|
||||||
className="flex flex-col gap-2 font-bold text-green-500 text-base first:text-2xl"
|
>
|
||||||
>
|
{formatCurrency(total, currency)}
|
||||||
{formatCurrency(total, currency)}
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
{!Object.entries(statsPerProject[project.code]?.totalIncomePerCurrency).length && (
|
||||||
{!Object.entries(statsPerProject[project.code]?.totalIncomePerCurrency).length && (
|
<div className="font-bold text-base first:text-2xl">0.00</div>
|
||||||
<div className="font-bold text-base first:text-2xl">0.00</div>
|
)}
|
||||||
)}
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="bg-gradient-to-br from-red-50/80 to-rose-50/60 p-3 rounded-xl border border-red-100/50">
|
||||||
|
<div className="text-sm font-medium text-muted-foreground">Expenses</div>
|
||||||
|
<div className="text-2xl font-bold text-red-500">
|
||||||
|
{Object.entries(statsPerProject[project.code]?.totalExpensesPerCurrency).map(
|
||||||
|
([currency, total]) => (
|
||||||
|
<div
|
||||||
|
key={currency}
|
||||||
|
className="flex flex-col gap-2 font-bold text-red-500 text-base first:text-2xl"
|
||||||
|
>
|
||||||
|
{formatCurrency(total, currency)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
{!Object.entries(statsPerProject[project.code]?.totalExpensesPerCurrency).length && (
|
||||||
|
<div className="font-bold text-base first:text-2xl">0.00</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="bg-gradient-to-br from-violet-50/80 to-indigo-50/60 p-3 rounded-xl border border-violet-100/50">
|
||||||
|
<div className="text-sm font-medium text-muted-foreground">Profit</div>
|
||||||
|
<div className="text-2xl font-bold">
|
||||||
|
{Object.entries(statsPerProject[project.code]?.profitPerCurrency).map(([currency, total]) => (
|
||||||
|
<div
|
||||||
|
key={currency}
|
||||||
|
className={`flex flex-col gap-2 items-center text-2xl font-bold ${
|
||||||
|
total >= 0 ? "text-green-500" : "text-red-500"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{formatCurrency(total, currency)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{!Object.entries(statsPerProject[project.code]?.profitPerCurrency).length && (
|
||||||
|
<div className="text-2xl font-bold">0.00</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
</CardContent>
|
||||||
<div className="text-sm font-medium text-muted-foreground">Expenses</div>
|
</Card>
|
||||||
<div className="text-2xl font-bold text-red-500">
|
</Link>
|
||||||
{Object.entries(statsPerProject[project.code]?.totalExpensesPerCurrency).map(([currency, total]) => (
|
|
||||||
<div key={currency} className="flex flex-col gap-2 font-bold text-red-500 text-base first:text-2xl">
|
|
||||||
{formatCurrency(total, currency)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
{!Object.entries(statsPerProject[project.code]?.totalExpensesPerCurrency).length && (
|
|
||||||
<div className="font-bold text-base first:text-2xl">0.00</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="text-sm font-medium text-muted-foreground">Profit</div>
|
|
||||||
<div className="text-2xl font-bold">
|
|
||||||
{Object.entries(statsPerProject[project.code]?.profitPerCurrency).map(([currency, total]) => (
|
|
||||||
<div
|
|
||||||
key={currency}
|
|
||||||
className={`flex flex-col gap-2 items-center text-2xl font-bold ${
|
|
||||||
total >= 0 ? "text-green-500" : "text-red-500"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{formatCurrency(total, currency)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
{!Object.entries(statsPerProject[project.code]?.profitPerCurrency).length && (
|
|
||||||
<div className="text-2xl font-bold">0.00</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
))}
|
))}
|
||||||
<Link
|
<Link
|
||||||
href="/settings/projects"
|
href="/settings/projects"
|
||||||
className="flex items-center justify-center gap-2 border-dashed border-2 border-gray-300 rounded-md p-4 text-muted-foreground hover:text-primary hover:border-primary"
|
className="flex items-center justify-center gap-2 border-dashed border-2 border-gradient-to-r rounded-lg p-6 text-muted-foreground transition-all duration-300 hover:scale-[1.02] hover:shadow-lg group"
|
||||||
>
|
>
|
||||||
<Plus className="h-4 w-4" />
|
<Plus className="h-5 w-5 group-hover:rotate-90 transition-transform duration-300" />
|
||||||
Create New Project
|
<span className="font-medium">Create New Project</span>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { getProjects } from "@/models/projects"
|
|||||||
import { getDashboardStats, getProjectStats } from "@/models/stats"
|
import { getDashboardStats, getProjectStats } from "@/models/stats"
|
||||||
import { TransactionFilters } from "@/models/transactions"
|
import { TransactionFilters } from "@/models/transactions"
|
||||||
import { ArrowDown, ArrowUp, BicepsFlexed } from "lucide-react"
|
import { ArrowDown, ArrowUp, BicepsFlexed } from "lucide-react"
|
||||||
|
import Link from "next/link"
|
||||||
|
|
||||||
export async function StatsWidget({ filters }: { filters: TransactionFilters }) {
|
export async function StatsWidget({ filters }: { filters: TransactionFilters }) {
|
||||||
const user = await getCurrentUser()
|
const user = await getCurrentUser()
|
||||||
@@ -27,61 +28,72 @@ export async function StatsWidget({ filters }: { filters: TransactionFilters })
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||||
<Card>
|
<Link href="/transactions?type=income">
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<Card className="bg-gradient-to-br from-white via-green-50/30 to-emerald-50/40 border-green-200/50 hover:shadow-lg transition-all duration-300 hover:scale-[1.02] cursor-pointer">
|
||||||
<CardTitle className="text-sm font-medium">Total Income</CardTitle>
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<ArrowUp className="h-4 w-4 text-green-500" />
|
<CardTitle className="text-sm font-medium">Total Income</CardTitle>
|
||||||
</CardHeader>
|
<ArrowUp className="h-4 w-4 text-green-500" />
|
||||||
<CardContent>
|
</CardHeader>
|
||||||
{Object.entries(stats.totalIncomePerCurrency).map(([currency, total]) => (
|
<CardContent>
|
||||||
<div key={currency} className="flex gap-2 items-center font-bold text-base first:text-2xl text-green-500">
|
{Object.entries(stats.totalIncomePerCurrency).map(([currency, total]) => (
|
||||||
{formatCurrency(total, currency)}
|
<div
|
||||||
</div>
|
key={currency}
|
||||||
))}
|
className="flex gap-2 items-center font-bold text-base first:text-2xl text-green-500"
|
||||||
{!Object.entries(stats.totalIncomePerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
>
|
||||||
</CardContent>
|
{formatCurrency(total, currency)}
|
||||||
</Card>
|
</div>
|
||||||
<Card>
|
))}
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
{!Object.entries(stats.totalIncomePerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
||||||
<CardTitle className="text-sm font-medium">Total Expenses</CardTitle>
|
</CardContent>
|
||||||
<ArrowDown className="h-4 w-4 text-red-500" />
|
</Card>
|
||||||
</CardHeader>
|
</Link>
|
||||||
<CardContent>
|
<Link href="/transactions?type=expense">
|
||||||
{Object.entries(stats.totalExpensesPerCurrency).map(([currency, total]) => (
|
<Card className="bg-gradient-to-br from-white via-red-50/30 to-rose-50/40 border-red-200/50 hover:shadow-lg transition-all duration-300 hover:scale-[1.02] cursor-pointer">
|
||||||
<div key={currency} className="flex gap-2 items-center font-bold text-base first:text-2xl text-red-500">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
{formatCurrency(total, currency)}
|
<CardTitle className="text-sm font-medium">Total Expenses</CardTitle>
|
||||||
</div>
|
<ArrowDown className="h-4 w-4 text-red-500" />
|
||||||
))}
|
</CardHeader>
|
||||||
{!Object.entries(stats.totalExpensesPerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
<CardContent>
|
||||||
</CardContent>
|
{Object.entries(stats.totalExpensesPerCurrency).map(([currency, total]) => (
|
||||||
</Card>
|
<div key={currency} className="flex gap-2 items-center font-bold text-base first:text-2xl text-red-500">
|
||||||
<Card>
|
{formatCurrency(total, currency)}
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
</div>
|
||||||
<CardTitle className="text-sm font-medium">Net Profit</CardTitle>
|
))}
|
||||||
<BicepsFlexed className="h-4 w-4" />
|
{!Object.entries(stats.totalExpensesPerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
||||||
</CardHeader>
|
</CardContent>
|
||||||
<CardContent>
|
</Card>
|
||||||
{Object.entries(stats.profitPerCurrency).map(([currency, total]) => (
|
</Link>
|
||||||
<div
|
<Link href="/transactions">
|
||||||
key={currency}
|
<Card className="bg-gradient-to-br from-white via-pink-50/30 to-indigo-50/40 border-pink-200/50 hover:shadow-lg transition-all duration-300 hover:scale-[1.02] cursor-pointer">
|
||||||
className={`flex gap-2 items-center font-bold text-base first:text-2xl ${
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
total >= 0 ? "text-green-500" : "text-red-500"
|
<CardTitle className="text-sm font-medium">Net Profit</CardTitle>
|
||||||
}`}
|
<BicepsFlexed className="h-4 w-4" />
|
||||||
>
|
</CardHeader>
|
||||||
{formatCurrency(total, currency)}
|
<CardContent>
|
||||||
</div>
|
{Object.entries(stats.profitPerCurrency).map(([currency, total]) => (
|
||||||
))}
|
<div
|
||||||
{!Object.entries(stats.profitPerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
key={currency}
|
||||||
</CardContent>
|
className={`flex gap-2 items-center font-bold text-base first:text-2xl ${
|
||||||
</Card>
|
total >= 0 ? "text-green-500" : "text-red-500"
|
||||||
<Card>
|
}`}
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
>
|
||||||
<CardTitle className="text-sm font-medium">Processed Transactions</CardTitle>
|
{formatCurrency(total, currency)}
|
||||||
</CardHeader>
|
</div>
|
||||||
<CardContent>
|
))}
|
||||||
<div className="text-2xl font-bold">{stats.invoicesProcessed}</div>
|
{!Object.entries(stats.profitPerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</Link>
|
||||||
|
<Link href="/transactions">
|
||||||
|
<Card className="bg-gradient-to-br from-white via-blue-50/30 to-indigo-50/40 border-blue-200/50 hover:shadow-lg transition-all duration-300 hover:scale-[1.02] cursor-pointer">
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
|
<CardTitle className="text-sm font-medium">Processed Transactions</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="text-2xl font-bold">{stats.invoicesProcessed}</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { deleteTransactionAction, saveTransactionAction } from "@/app/(app)/transactions/actions"
|
import { deleteTransactionAction, saveTransactionAction } from "@/app/(app)/transactions/actions"
|
||||||
|
import { ItemsDetectTool } from "@/components/agents/items-detect"
|
||||||
|
import ToolWindow from "@/components/agents/tool-window"
|
||||||
import { FormError } from "@/components/forms/error"
|
import { FormError } from "@/components/forms/error"
|
||||||
import { FormSelectCategory } from "@/components/forms/select-category"
|
import { FormSelectCategory } from "@/components/forms/select-category"
|
||||||
import { FormSelectCurrency } from "@/components/forms/select-currency"
|
import { FormSelectCurrency } from "@/components/forms/select-currency"
|
||||||
@@ -8,14 +10,12 @@ import { FormSelectProject } from "@/components/forms/select-project"
|
|||||||
import { FormSelectType } from "@/components/forms/select-type"
|
import { FormSelectType } from "@/components/forms/select-type"
|
||||||
import { FormInput, FormTextarea } from "@/components/forms/simple"
|
import { FormInput, FormTextarea } from "@/components/forms/simple"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { TransactionData } from "@/models/transactions"
|
||||||
import { Category, Currency, Field, Project, Transaction } from "@/prisma/client"
|
import { Category, Currency, Field, Project, Transaction } from "@/prisma/client"
|
||||||
import { format } from "date-fns"
|
import { format } from "date-fns"
|
||||||
import { Loader2, Save, Trash2 } from "lucide-react"
|
import { Loader2, Save, Trash2 } from "lucide-react"
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
import { startTransition, useActionState, useEffect, useMemo, useState } from "react"
|
import { startTransition, useActionState, useEffect, useMemo, useState } from "react"
|
||||||
import ToolWindow from "@/components/agents/tool-window"
|
|
||||||
import { ItemsDetectTool } from "@/components/agents/items-detect"
|
|
||||||
import { TransactionData } from "@/models/transactions"
|
|
||||||
|
|
||||||
export default function TransactionEditForm({
|
export default function TransactionEditForm({
|
||||||
transaction,
|
transaction,
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export type TransactionFilters = {
|
|||||||
ordering?: string
|
ordering?: string
|
||||||
categoryCode?: string
|
categoryCode?: string
|
||||||
projectCode?: string
|
projectCode?: string
|
||||||
|
type?: string
|
||||||
page?: number
|
page?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +55,11 @@ export const getTransactions = cache(
|
|||||||
if (filters) {
|
if (filters) {
|
||||||
if (filters.search) {
|
if (filters.search) {
|
||||||
where.OR = [
|
where.OR = [
|
||||||
{ name: { contains: filters.search, mode: 'insensitive' } },
|
{ name: { contains: filters.search, mode: "insensitive" } },
|
||||||
{ merchant: { contains: filters.search, mode: 'insensitive' } },
|
{ merchant: { contains: filters.search, mode: "insensitive" } },
|
||||||
{ description: { contains: filters.search, mode: 'insensitive' } },
|
{ description: { contains: filters.search, mode: "insensitive" } },
|
||||||
{ note: { contains: filters.search, mode: 'insensitive' } },
|
{ note: { contains: filters.search, mode: "insensitive" } },
|
||||||
{ text: { contains: filters.search, mode: 'insensitive' } },
|
{ text: { contains: filters.search, mode: "insensitive" } },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +78,10 @@ export const getTransactions = cache(
|
|||||||
where.projectCode = filters.projectCode
|
where.projectCode = filters.projectCode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filters.type) {
|
||||||
|
where.type = filters.type
|
||||||
|
}
|
||||||
|
|
||||||
if (filters.ordering) {
|
if (filters.ordering) {
|
||||||
const isDesc = filters.ordering.startsWith("-")
|
const isDesc = filters.ordering.startsWith("-")
|
||||||
const field = isDesc ? filters.ordering.slice(1) : filters.ordering
|
const field = isDesc ? filters.ordering.slice(1) : filters.ordering
|
||||||
@@ -148,7 +153,7 @@ export const updateTransaction = async (id: string, userId: string, data: Transa
|
|||||||
data: {
|
data: {
|
||||||
...standard,
|
...standard,
|
||||||
extra: extra,
|
extra: extra,
|
||||||
items: data.items ? data.items as Prisma.InputJsonValue : [],
|
items: data.items ? (data.items as Prisma.InputJsonValue) : [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user