feat: rename keep-notes to memento-note, migrate to PostgreSQL, fix MCP bugs
- Rename directory keep-notes -> memento-note with all code references - Prisma: SQLite -> PostgreSQL (both app and MCP server schemas) - Sync MCP schema with main app (add missing fields, relations, indexes) - Delete 17 SQLite migrations (clean slate for PostgreSQL) - Remove SQLite dependencies (@libsql/client, better-sqlite3, etc.) - Fix MCP server: hardcoded Windows DB paths -> DATABASE_URL env var - Fix MCP server: .dockerignore excluded index-sse.js (SSE mode broken) - MCP Dockerfile: node:20 -> node:22 - Docker Compose: add postgres service, remove SQLite volume - Generate favicon.ico, icon-192.png, icon-512.png, apple-icon.png - Update layout.tsx icons and manifest.json for PNG icons - Update all .env files for PostgreSQL - Rewrite README.md with updated sections - Remove mcp-server/node_modules and prisma/client-generated from git tracking Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
70
memento-note/components/admin-metrics.tsx
Normal file
70
memento-note/components/admin-metrics.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
'use client'
|
||||
|
||||
import { Card } from '@/components/ui/card'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
export interface MetricItem {
|
||||
title: string
|
||||
value: string | number
|
||||
trend?: {
|
||||
value: number
|
||||
isPositive: boolean
|
||||
}
|
||||
icon?: React.ReactNode
|
||||
}
|
||||
|
||||
export interface AdminMetricsProps {
|
||||
metrics: MetricItem[]
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function AdminMetrics({ metrics, className }: AdminMetricsProps) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{metrics.map((metric, index) => (
|
||||
<Card
|
||||
key={index}
|
||||
className="p-6 bg-white dark:bg-zinc-900 border-gray-200 dark:border-gray-800"
|
||||
>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1">
|
||||
<p className="text-sm font-medium text-gray-600 dark:text-gray-400 mb-2">
|
||||
{metric.title}
|
||||
</p>
|
||||
<p className="text-2xl font-bold text-gray-900 dark:text-white">
|
||||
{metric.value}
|
||||
</p>
|
||||
{metric.trend && (
|
||||
<div className="flex items-center gap-1 mt-2">
|
||||
<span
|
||||
className={cn(
|
||||
'text-xs font-medium',
|
||||
metric.trend.isPositive
|
||||
? 'text-green-600 dark:text-green-400'
|
||||
: 'text-red-600 dark:text-red-400'
|
||||
)}
|
||||
>
|
||||
{metric.trend.isPositive ? '↑' : '↓'} {Math.abs(metric.trend.value)}%
|
||||
</span>
|
||||
<span className="text-xs text-gray-500 dark:text-gray-400">
|
||||
vs last period
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{metric.icon && (
|
||||
<div className="p-2 bg-gray-100 dark:bg-zinc-800 rounded-lg">
|
||||
{metric.icon}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user