feat: initial commit - finanzas app
Complete personal finance management application with: - Dashboard with financial metrics and alerts - Credit card management and payments - Fixed and variable debt tracking - Monthly budget planning - Intelligent alert system - Responsive design with Tailwind CSS Tech stack: Next.js 14, TypeScript, Zustand, Recharts 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
112
components/alerts/AlertBanner.tsx
Normal file
112
components/alerts/AlertBanner.tsx
Normal file
@@ -0,0 +1,112 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { Check, X } from 'lucide-react'
|
||||
import { Alert } from '@/lib/types'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { AlertIcon } from './AlertIcon'
|
||||
|
||||
interface AlertBannerProps {
|
||||
alert: Alert
|
||||
onDismiss: () => void
|
||||
onMarkRead: () => void
|
||||
}
|
||||
|
||||
const severityStyles = {
|
||||
info: {
|
||||
bg: 'bg-blue-900/50',
|
||||
border: 'border-l-blue-500',
|
||||
icon: 'text-blue-400',
|
||||
},
|
||||
warning: {
|
||||
bg: 'bg-amber-900/50',
|
||||
border: 'border-l-amber-500',
|
||||
icon: 'text-amber-400',
|
||||
},
|
||||
danger: {
|
||||
bg: 'bg-red-900/50',
|
||||
border: 'border-l-red-500',
|
||||
icon: 'text-red-400',
|
||||
},
|
||||
}
|
||||
|
||||
export function AlertBanner({ alert, onDismiss, onMarkRead }: AlertBannerProps) {
|
||||
const [isVisible, setIsVisible] = useState(true)
|
||||
const [isExiting, setIsExiting] = useState(false)
|
||||
const styles = severityStyles[alert.severity]
|
||||
|
||||
const handleDismiss = () => {
|
||||
setIsExiting(true)
|
||||
setTimeout(() => {
|
||||
setIsVisible(false)
|
||||
onDismiss()
|
||||
}, 300)
|
||||
}
|
||||
|
||||
const handleMarkRead = () => {
|
||||
setIsExiting(true)
|
||||
setTimeout(() => {
|
||||
setIsVisible(false)
|
||||
onMarkRead()
|
||||
}, 300)
|
||||
}
|
||||
|
||||
if (!isVisible) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'relative overflow-hidden rounded-r-lg border-l-4 p-4',
|
||||
'transition-all duration-300 ease-out',
|
||||
'animate-in slide-in-from-top-2',
|
||||
isExiting && 'animate-out slide-out-to-top-2 opacity-0',
|
||||
styles.bg,
|
||||
styles.border
|
||||
)}
|
||||
role="alert"
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className={cn('flex-shrink-0 mt-0.5', styles.icon)}>
|
||||
<AlertIcon type={alert.type} />
|
||||
</div>
|
||||
|
||||
<div className="flex-1 min-w-0">
|
||||
<h4 className="font-semibold text-white text-sm">{alert.title}</h4>
|
||||
<p className="mt-1 text-sm text-gray-300">{alert.message}</p>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-1 flex-shrink-0">
|
||||
{!alert.isRead && (
|
||||
<button
|
||||
onClick={handleMarkRead}
|
||||
className={cn(
|
||||
'p-1.5 rounded-md transition-colors',
|
||||
'text-gray-400 hover:text-white hover:bg-white/10',
|
||||
'focus:outline-none focus:ring-2 focus:ring-white/20'
|
||||
)}
|
||||
title="Marcar como leída"
|
||||
aria-label="Marcar como leída"
|
||||
>
|
||||
<Check className="h-4 w-4" />
|
||||
</button>
|
||||
)}
|
||||
|
||||
<button
|
||||
onClick={handleDismiss}
|
||||
className={cn(
|
||||
'p-1.5 rounded-md transition-colors',
|
||||
'text-gray-400 hover:text-white hover:bg-white/10',
|
||||
'focus:outline-none focus:ring-2 focus:ring-white/20'
|
||||
)}
|
||||
title="Cerrar"
|
||||
aria-label="Cerrar alerta"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user