Initial commit — eLegal Software monorepo
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Calculator, BarChart3, Clock, FileText } from 'lucide-react';
|
||||
import type { ComponentType } from 'react';
|
||||
import { PublicLayout, PublicHero } from '@/components/public/PublicLayout';
|
||||
import { useToolsOnline, type ToolName } from '@/hooks/useToolUsage';
|
||||
|
||||
interface Tool {
|
||||
slug: ToolName;
|
||||
title: string;
|
||||
description: string;
|
||||
icon: ComponentType<{ className?: string }>;
|
||||
}
|
||||
|
||||
const TOOLS: Tool[] = [
|
||||
{
|
||||
slug: 'hourly-rate-calculator',
|
||||
title: 'Hourly Rate Calculator',
|
||||
description:
|
||||
'Work backwards from your target take-home to find the hourly rate you actually need to charge.',
|
||||
icon: Calculator,
|
||||
},
|
||||
{
|
||||
slug: 'case-profitability',
|
||||
title: 'Case Profitability Analyzer',
|
||||
description: 'Plug in hours, rates, and case expenses to see whether a matter is making you money.',
|
||||
icon: BarChart3,
|
||||
},
|
||||
{
|
||||
slug: 'billable-hours-tracker',
|
||||
title: 'Billable Hours Tracker',
|
||||
description: 'A no-signup timer with manual entries and CSV export. Saved locally to your browser.',
|
||||
icon: Clock,
|
||||
},
|
||||
{
|
||||
slug: 'document-templates',
|
||||
title: 'Document Templates',
|
||||
description: 'Fill in a few fields, download a clean text version of common law-firm documents.',
|
||||
icon: FileText,
|
||||
},
|
||||
];
|
||||
|
||||
export default function ToolsIndexPage() {
|
||||
const online = useToolsOnline();
|
||||
|
||||
return (
|
||||
<PublicLayout>
|
||||
<PublicHero
|
||||
eyebrow="Free Legal Tools"
|
||||
title="Practical calculators for your practice"
|
||||
description="No signup, no email. Use them as much as you like. If you want everything in one place, that's what eLegal Software is for."
|
||||
/>
|
||||
|
||||
<section className="container py-16">
|
||||
<div className="grid gap-5 md:grid-cols-2">
|
||||
{TOOLS.map((tool) => {
|
||||
const count = online.data?.online[tool.slug] ?? 0;
|
||||
return (
|
||||
<Link
|
||||
key={tool.slug}
|
||||
to={`/tools/${tool.slug}`}
|
||||
className="group rounded-2xl border border-ink-100 bg-white p-6 hover:border-brand-200 hover:shadow-lg hover:shadow-brand-500/5 transition flex flex-col"
|
||||
>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="grid h-12 w-12 place-items-center rounded-xl bg-brand-50 text-brand-600 group-hover:bg-brand-500 group-hover:text-white transition">
|
||||
<tool.icon className="h-5 w-5" />
|
||||
</div>
|
||||
<span className="inline-flex items-center gap-1.5 rounded-full bg-emerald-50 text-emerald-700 px-2 py-0.5 text-[11px] font-semibold">
|
||||
<span className="h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse" />
|
||||
{count} online
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="mt-5 text-lg font-semibold text-ink-900">{tool.title}</h3>
|
||||
<p className="mt-2 text-sm leading-relaxed text-ink-600">{tool.description}</p>
|
||||
<span className="mt-4 text-sm font-semibold text-brand-600 group-hover:text-brand-700">
|
||||
Open tool →
|
||||
</span>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
</PublicLayout>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user