mirror of
https://github.com/marcogll/TaxHacker_s23.git
synced 2026-01-13 13:25:18 +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 { getSettings } from "@/models/settings"
|
||||
import { getTransactionById } from "@/models/transactions"
|
||||
import { notFound } from "next/navigation"
|
||||
import Link from "next/link"
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
export default async function TransactionPage({ params }: { params: Promise<{ transactionId: string }> }) {
|
||||
const { transactionId } = await params
|
||||
@@ -32,7 +32,7 @@ export default async function TransactionPage({ params }: { params: Promise<{ tr
|
||||
|
||||
return (
|
||||
<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 && (
|
||||
<div className="w-full flex flex-col gap-1 rounded-md bg-yellow-50 p-5">
|
||||
<span>
|
||||
@@ -47,7 +47,7 @@ export default async function TransactionPage({ params }: { params: Promise<{ tr
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="w-full p-5 bg-accent">
|
||||
<div className="w-full p-5">
|
||||
<TransactionEditForm
|
||||
transaction={transaction}
|
||||
categories={categories}
|
||||
|
||||
@@ -38,29 +38,32 @@ export default async function UnsortedPage() {
|
||||
{files.length > 1 && <AnalyzeAllButton />}
|
||||
</header>
|
||||
|
||||
{config.selfHosted.isEnabled && !settings.openai_api_key && !settings.google_api_key && !settings.mistral_api_key && (
|
||||
<Alert>
|
||||
<Settings className="h-4 w-4 mt-2" />
|
||||
<div className="flex flex-row justify-between pt-2">
|
||||
<div className="flex flex-col">
|
||||
<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>
|
||||
{config.selfHosted.isEnabled &&
|
||||
!settings.openai_api_key &&
|
||||
!settings.google_api_key &&
|
||||
!settings.mistral_api_key && (
|
||||
<Alert>
|
||||
<Settings className="h-4 w-4 mt-2" />
|
||||
<div className="flex flex-row justify-between pt-2">
|
||||
<div className="flex flex-col">
|
||||
<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>
|
||||
<Link href="/settings/llm">
|
||||
<Button>Go to Settings</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</Alert>
|
||||
)}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<main className="flex flex-col gap-5">
|
||||
{files.map((file) => (
|
||||
<Card
|
||||
key={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]">
|
||||
<Card>
|
||||
|
||||
@@ -6,23 +6,32 @@ import Link from "next/link"
|
||||
|
||||
export default function LandingPage() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-[#FAFAFA]">
|
||||
<header className="py-6 px-4 md:px-8 bg-white/80 backdrop-blur-md shadow-sm fixed w-full z-10">
|
||||
<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/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">
|
||||
<Link href="/" className="flex items-center gap-2">
|
||||
<Image src="/logo/256.png" alt="Logo" width={32} height={32} className="h-8" />
|
||||
<Link href="/" className="flex items-center gap-2 group">
|
||||
<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>
|
||||
</Link>
|
||||
<div className="flex gap-1 md:gap-4 text-xs md:text-sm">
|
||||
<Link
|
||||
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
|
||||
</Link>
|
||||
<Link
|
||||
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
|
||||
</Link>
|
||||
@@ -31,35 +40,40 @@ export default function LandingPage() {
|
||||
</header>
|
||||
|
||||
{/* Hero Section */}
|
||||
<section className="pt-32 pb-16 px-8">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<section className="pt-32 pb-16 px-8 relative overflow-hidden">
|
||||
{/* 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="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
|
||||
</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
|
||||
</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
|
||||
</p>
|
||||
<div className="flex gap-4 justify-center text-sm md:text-lg">
|
||||
<Link
|
||||
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
|
||||
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>
|
||||
</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="absolute inset-0 bg-gradient-to-b from-blue-500/5 to-transparent z-10" />
|
||||
<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-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">
|
||||
<source src="/landing/video.mp4" type="video/mp4" />
|
||||
<Image src="/landing/title.webp" alt="TaxHacker" width={1980} height={1224} priority />
|
||||
@@ -69,133 +83,179 @@ export default function LandingPage() {
|
||||
</section>
|
||||
|
||||
{/* Features Section */}
|
||||
<section className="py-20 px-8">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<section className="py-20 px-8 relative">
|
||||
<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">
|
||||
<h2 className="flex flex-col gap-3 mb-4 bg-gradient-to-r from-gray-900 to-gray-600 bg-clip-text text-transparent">
|
||||
<span className="text-6xl font-semibold text-muted-foreground">F∗ck Taxes</span>
|
||||
<span className="text-4xl font-bold">TaxHacker can save you time, money and nerves</span>
|
||||
<h2 className="flex flex-col gap-3 mb-4">
|
||||
<span className="text-6xl font-bold bg-gradient-to-r from-pink-600 to-indigo-600 bg-clip-text text-transparent">
|
||||
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>
|
||||
</div>
|
||||
|
||||
{/* 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="inline-block px-3 py-1 rounded-full bg-blue-50 text-blue-600 text-sm font-medium mb-4">
|
||||
LLM-Powered
|
||||
<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
|
||||
</div>
|
||||
<h3 className="text-2xl font-semibold mb-4">Analyze photos and invoices with AI</h3>
|
||||
<ul className="space-y-3 text-gray-600">
|
||||
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-blue-700 to-indigo-700 bg-clip-text text-transparent">
|
||||
Analyze photos and invoices with AI
|
||||
</h3>
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
</ul>
|
||||
</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} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 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="inline-block px-3 py-1 rounded-full bg-green-50 text-green-600 text-sm font-medium mb-4">
|
||||
Currency Converter
|
||||
<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
|
||||
</div>
|
||||
<h3 className="text-2xl font-semibold mb-4">Automatically convert currencies</h3>
|
||||
<ul className="space-y-3 text-gray-600">
|
||||
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-green-700 to-emerald-700 bg-clip-text text-transparent">
|
||||
Automatically convert currencies
|
||||
</h3>
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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.)
|
||||
</li>
|
||||
</ul>
|
||||
</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} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 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-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 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-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} />
|
||||
</div>
|
||||
<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">
|
||||
Filters
|
||||
<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
|
||||
</div>
|
||||
<h3 className="text-2xl font-semibold mb-4">Organize expenses and income</h3>
|
||||
<ul className="space-y-3 text-gray-600">
|
||||
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-pink-700 to-rose-700 bg-clip-text text-transparent">
|
||||
Organize expenses and income
|
||||
</h3>
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
</ul>
|
||||
</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 */}
|
||||
<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-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 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-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} />
|
||||
</div>
|
||||
<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">
|
||||
Customization
|
||||
<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
|
||||
</div>
|
||||
<h3 className="text-2xl font-semibold mb-4">Create custom LLM promts to extract anything</h3>
|
||||
<ul className="space-y-3 text-gray-600">
|
||||
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-violet-700 to-purple-700 bg-clip-text text-transparent">
|
||||
Create custom LLM promts to extract anything
|
||||
</h3>
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
</ul>
|
||||
@@ -203,30 +263,32 @@ export default function LandingPage() {
|
||||
</div>
|
||||
|
||||
{/* 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-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 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-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} />
|
||||
</div>
|
||||
<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">
|
||||
Export
|
||||
<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
|
||||
</div>
|
||||
<h3 className="text-2xl font-semibold mb-4">Your Data — Your Rules</h3>
|
||||
<ul className="space-y-3 text-gray-600">
|
||||
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-orange-700 to-amber-700 bg-clip-text text-transparent">
|
||||
Your Data — Your Rules
|
||||
</h3>
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
</ul>
|
||||
@@ -236,83 +298,84 @@ export default function LandingPage() {
|
||||
</section>
|
||||
|
||||
{/* Deployment Options */}
|
||||
<section id="start" className="py-20 px-8 bg-white scroll-mt-20">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<section
|
||||
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">
|
||||
<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
|
||||
</h2>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 gap-16">
|
||||
{/* 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="inline-block px-3 py-1 rounded-full bg-violet-50 text-violet-600 text-sm font-medium mb-4">
|
||||
Use Your Own Server
|
||||
<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-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
|
||||
</div>
|
||||
<h3 className="text-2xl font-semibold mb-4">
|
||||
<h3 className="text-2xl font-bold mb-4">
|
||||
<ColoredText>Self-Hosted Edition</ColoredText>
|
||||
</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">
|
||||
<span className="text-blue-600 mr-2">✓</span>
|
||||
<span className="text-indigo-600 mr-3 text-lg">🆓</span>
|
||||
Free and open source
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<li className="flex items-center">
|
||||
<span className="text-blue-600 mr-2">✓</span>
|
||||
Bring your own OpenAI keys
|
||||
<span className="text-indigo-600 mr-3 text-lg">🔑</span>
|
||||
Bring your own keys (OpenAI, Gemini, Mistral, etc.)
|
||||
</li>
|
||||
</ul>
|
||||
<Link
|
||||
href="https://github.com/vas3k/TaxHacker"
|
||||
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>
|
||||
</div>
|
||||
|
||||
{/* 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="absolute top-4 right-4">
|
||||
<span className="px-3 py-1 bg-gray-100 text-gray-600 rounded-full text-sm">Coming Soon</span>
|
||||
<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="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">
|
||||
☁️ We Host It For You
|
||||
</div>
|
||||
<div className="inline-block px-3 py-1 rounded-full bg-purple-50 text-purple-600 text-sm font-medium mb-4">
|
||||
We Host It For You
|
||||
</div>
|
||||
<h3 className="text-2xl font-semibold mb-4">
|
||||
<h3 className="text-2xl font-bold mb-4">
|
||||
<ColoredText>Cloud Edition</ColoredText>
|
||||
</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">
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
</ul>
|
||||
<Link
|
||||
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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -320,105 +383,116 @@ export default function LandingPage() {
|
||||
</section>
|
||||
|
||||
{/* Upcoming Features */}
|
||||
<section className="py-20 px-8 bg-gradient-to-b from-white to-gray-50 mt-28">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<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="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">
|
||||
<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
|
||||
</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.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-8 mb-16">
|
||||
{/* 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">
|
||||
<span className="text-2xl">🤖</span>
|
||||
<h3 className="text-xl font-semibold">Better AI Analytics & Agents</h3>
|
||||
<span className="text-3xl">🤖</span>
|
||||
<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>
|
||||
<ul className="space-y-3 text-gray-600">
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* 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">
|
||||
<span className="text-2xl">📂</span>
|
||||
<h3 className="text-xl font-semibold">Smart Reports & Reminders</h3>
|
||||
<span className="text-3xl">📊</span>
|
||||
<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>
|
||||
<ul className="space-y-3 text-gray-600">
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* 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">
|
||||
<span className="text-2xl">📥</span>
|
||||
<h3 className="text-xl font-semibold">Multiple Transaction Review</h3>
|
||||
<span className="text-3xl">📥</span>
|
||||
<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>
|
||||
<ul className="space-y-3 text-gray-600">
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* 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">
|
||||
<span className="text-2xl">🤯</span>
|
||||
<h3 className="text-xl font-semibold">Presets and Plugins</h3>
|
||||
<span className="text-3xl">🧩</span>
|
||||
<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>
|
||||
<ul className="space-y-3 text-gray-600">
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
<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
|
||||
</li>
|
||||
</ul>
|
||||
@@ -430,10 +504,13 @@ export default function LandingPage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer className="py-8 px-8 bg-white">
|
||||
<div className="max-w-7xl mx-auto text-center text-sm text-gray-500">
|
||||
<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-600">
|
||||
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
|
||||
</Link>
|
||||
</div>
|
||||
@@ -441,25 +518,37 @@ export default function LandingPage() {
|
||||
<section className="py-12 px-8">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<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
|
||||
</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
|
||||
</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
|
||||
</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
|
||||
</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
|
||||
</Link>
|
||||
<Link
|
||||
href="https://github.com/vas3k/TaxHacker"
|
||||
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
|
||||
</Link>
|
||||
|
||||
@@ -16,75 +16,83 @@ export function ProjectsWidget({
|
||||
return (
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
{projects.map((project) => (
|
||||
<Card key={project.code}>
|
||||
<CardHeader>
|
||||
<CardTitle>
|
||||
<Link href={`/transactions?projectCode=${project.code}`}>
|
||||
<Badge className="text-lg" style={{ backgroundColor: project.color }}>
|
||||
<Link key={project.code} href={`/transactions?projectCode=${project.code}`}>
|
||||
<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">
|
||||
<CardHeader className="group-hover:translate-y-[-2px] transition-transform duration-300">
|
||||
<CardTitle>
|
||||
<Badge
|
||||
className="text-lg shadow-md hover:shadow-lg transition-all duration-300"
|
||||
style={{ backgroundColor: project.color }}
|
||||
>
|
||||
{project.name}
|
||||
</Badge>
|
||||
</Link>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex flex-wrap gap-4 justify-between items-center">
|
||||
<div>
|
||||
<div className="text-sm font-medium text-muted-foreground">Income</div>
|
||||
<div className="text-2xl font-bold text-green-500">
|
||||
{Object.entries(statsPerProject[project.code]?.totalIncomePerCurrency).map(([currency, total]) => (
|
||||
<div
|
||||
key={currency}
|
||||
className="flex flex-col gap-2 font-bold text-green-500 text-base first:text-2xl"
|
||||
>
|
||||
{formatCurrency(total, currency)}
|
||||
</div>
|
||||
))}
|
||||
{!Object.entries(statsPerProject[project.code]?.totalIncomePerCurrency).length && (
|
||||
<div className="font-bold text-base first:text-2xl">0.00</div>
|
||||
)}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="group-hover:translate-y-[-1px] transition-transform duration-300">
|
||||
<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 className="text-sm font-medium text-muted-foreground">Income</div>
|
||||
<div className="text-2xl font-bold text-green-500">
|
||||
{Object.entries(statsPerProject[project.code]?.totalIncomePerCurrency).map(([currency, total]) => (
|
||||
<div
|
||||
key={currency}
|
||||
className="flex flex-col gap-2 font-bold text-green-500 text-base first:text-2xl"
|
||||
>
|
||||
{formatCurrency(total, currency)}
|
||||
</div>
|
||||
))}
|
||||
{!Object.entries(statsPerProject[project.code]?.totalIncomePerCurrency).length && (
|
||||
<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 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>
|
||||
<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>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
))}
|
||||
<Link
|
||||
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" />
|
||||
Create New Project
|
||||
<Plus className="h-5 w-5 group-hover:rotate-90 transition-transform duration-300" />
|
||||
<span className="font-medium">Create New Project</span>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -7,6 +7,7 @@ import { getProjects } from "@/models/projects"
|
||||
import { getDashboardStats, getProjectStats } from "@/models/stats"
|
||||
import { TransactionFilters } from "@/models/transactions"
|
||||
import { ArrowDown, ArrowUp, BicepsFlexed } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
|
||||
export async function StatsWidget({ filters }: { filters: TransactionFilters }) {
|
||||
const user = await getCurrentUser()
|
||||
@@ -27,61 +28,72 @@ export async function StatsWidget({ filters }: { filters: TransactionFilters })
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Income</CardTitle>
|
||||
<ArrowUp className="h-4 w-4 text-green-500" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{Object.entries(stats.totalIncomePerCurrency).map(([currency, total]) => (
|
||||
<div key={currency} className="flex gap-2 items-center font-bold text-base first:text-2xl text-green-500">
|
||||
{formatCurrency(total, currency)}
|
||||
</div>
|
||||
))}
|
||||
{!Object.entries(stats.totalIncomePerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Expenses</CardTitle>
|
||||
<ArrowDown className="h-4 w-4 text-red-500" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{Object.entries(stats.totalExpensesPerCurrency).map(([currency, total]) => (
|
||||
<div key={currency} className="flex gap-2 items-center font-bold text-base first:text-2xl text-red-500">
|
||||
{formatCurrency(total, currency)}
|
||||
</div>
|
||||
))}
|
||||
{!Object.entries(stats.totalExpensesPerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Net Profit</CardTitle>
|
||||
<BicepsFlexed className="h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{Object.entries(stats.profitPerCurrency).map(([currency, total]) => (
|
||||
<div
|
||||
key={currency}
|
||||
className={`flex gap-2 items-center font-bold text-base first:text-2xl ${
|
||||
total >= 0 ? "text-green-500" : "text-red-500"
|
||||
}`}
|
||||
>
|
||||
{formatCurrency(total, currency)}
|
||||
</div>
|
||||
))}
|
||||
{!Object.entries(stats.profitPerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<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 href="/transactions?type=income">
|
||||
<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">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Income</CardTitle>
|
||||
<ArrowUp className="h-4 w-4 text-green-500" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{Object.entries(stats.totalIncomePerCurrency).map(([currency, total]) => (
|
||||
<div
|
||||
key={currency}
|
||||
className="flex gap-2 items-center font-bold text-base first:text-2xl text-green-500"
|
||||
>
|
||||
{formatCurrency(total, currency)}
|
||||
</div>
|
||||
))}
|
||||
{!Object.entries(stats.totalIncomePerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
<Link href="/transactions?type=expense">
|
||||
<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">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total Expenses</CardTitle>
|
||||
<ArrowDown className="h-4 w-4 text-red-500" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{Object.entries(stats.totalExpensesPerCurrency).map(([currency, total]) => (
|
||||
<div key={currency} className="flex gap-2 items-center font-bold text-base first:text-2xl text-red-500">
|
||||
{formatCurrency(total, currency)}
|
||||
</div>
|
||||
))}
|
||||
{!Object.entries(stats.totalExpensesPerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
<Link href="/transactions">
|
||||
<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">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Net Profit</CardTitle>
|
||||
<BicepsFlexed className="h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{Object.entries(stats.profitPerCurrency).map(([currency, total]) => (
|
||||
<div
|
||||
key={currency}
|
||||
className={`flex gap-2 items-center font-bold text-base first:text-2xl ${
|
||||
total >= 0 ? "text-green-500" : "text-red-500"
|
||||
}`}
|
||||
>
|
||||
{formatCurrency(total, currency)}
|
||||
</div>
|
||||
))}
|
||||
{!Object.entries(stats.profitPerCurrency).length && <div className="text-2xl font-bold">0.00</div>}
|
||||
</CardContent>
|
||||
</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>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"use client"
|
||||
|
||||
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 { FormSelectCategory } from "@/components/forms/select-category"
|
||||
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 { FormInput, FormTextarea } from "@/components/forms/simple"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { TransactionData } from "@/models/transactions"
|
||||
import { Category, Currency, Field, Project, Transaction } from "@/prisma/client"
|
||||
import { format } from "date-fns"
|
||||
import { Loader2, Save, Trash2 } from "lucide-react"
|
||||
import { useRouter } from "next/navigation"
|
||||
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({
|
||||
transaction,
|
||||
|
||||
@@ -31,6 +31,7 @@ export type TransactionFilters = {
|
||||
ordering?: string
|
||||
categoryCode?: string
|
||||
projectCode?: string
|
||||
type?: string
|
||||
page?: number
|
||||
}
|
||||
|
||||
@@ -54,11 +55,11 @@ export const getTransactions = cache(
|
||||
if (filters) {
|
||||
if (filters.search) {
|
||||
where.OR = [
|
||||
{ name: { contains: filters.search, mode: 'insensitive' } },
|
||||
{ merchant: { contains: filters.search, mode: 'insensitive' } },
|
||||
{ description: { contains: filters.search, mode: 'insensitive' } },
|
||||
{ note: { contains: filters.search, mode: 'insensitive' } },
|
||||
{ text: { contains: filters.search, mode: 'insensitive' } },
|
||||
{ name: { contains: filters.search, mode: "insensitive" } },
|
||||
{ merchant: { contains: filters.search, mode: "insensitive" } },
|
||||
{ description: { contains: filters.search, mode: "insensitive" } },
|
||||
{ note: { contains: filters.search, mode: "insensitive" } },
|
||||
{ text: { contains: filters.search, mode: "insensitive" } },
|
||||
]
|
||||
}
|
||||
|
||||
@@ -77,6 +78,10 @@ export const getTransactions = cache(
|
||||
where.projectCode = filters.projectCode
|
||||
}
|
||||
|
||||
if (filters.type) {
|
||||
where.type = filters.type
|
||||
}
|
||||
|
||||
if (filters.ordering) {
|
||||
const isDesc = filters.ordering.startsWith("-")
|
||||
const field = isDesc ? filters.ordering.slice(1) : filters.ordering
|
||||
@@ -148,7 +153,7 @@ export const updateTransaction = async (id: string, userId: string, data: Transa
|
||||
data: {
|
||||
...standard,
|
||||
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