# đ Notification System Setup Guide
## Overview
The notification system has been implemented to notify users about:
- â
**Action Notifications**: When users upload, analyze, or delete contracts
- đ **Deadline Notifications**: When contracts are expiring (30, 15, 7 days)
- đą **Toast Notifications**: Immediate UI feedback for all actions
- đ **Notification Center**: Persistent notification history accessible from the dashboard
## Database Migration
### Step 1: Update Your Database Schema
Run the following Prisma command to create the necessary database tables:
```bash
npx prisma migrate dev --name add_notifications
```
This will:
1. Create the `Notification` table
2. Create the `NotificationType` enum
3. Add the `notifications` relationship to the `User` model
4. Add the `notifications` relationship to the `Contract` model
### Step 2: Database Schema Overview
The migration adds:
```sql
-- Notification table with indexes
CREATE TABLE "Notification" (
id TEXT PRIMARY KEY,
userId TEXT NOT NULL,
contractId TEXT,
type "NotificationType" NOT NULL,
title VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
icon VARCHAR(100),
actionType VARCHAR(100),
actionData JSONB,
read BOOLEAN DEFAULT false,
createdAt TIMESTAMP DEFAULT now(),
expiresAt TIMESTAMP,
FOREIGN KEY (userId) REFERENCES "User"(id) ON DELETE CASCADE,
FOREIGN KEY (contractId) REFERENCES "Contract"(id) ON DELETE SET NULL
);
-- Notification Type Enum
CREATE TYPE "NotificationType" AS ENUM (
'SUCCESS',
'WARNING',
'ERROR',
'INFO',
'DEADLINE'
);
```
## Architecture Overview
### 1. **Notification Service** (`lib/services/notification.service.ts`)
Core service handling all notification operations:
- Create notifications
- Fetch unread/all notifications
- Mark as read
- Delete notifications
- Check for upcoming deadlines
- Cleanup expired notifications
**Key Methods:**
- `create(input)` - Create new notification
- `getUnread(userId, limit)` - Fetch unread notifications
- `getUnreadCount(userId)` - Get badge count
- `checkUpcomingDeadlines(userId)` - Scan contracts and create deadline notifications
- `cleanupExpired()` - Remove expired notifications (run periodically)
### 2. **Notification Actions** (`lib/actions/notification.action.ts`)
Server actions for client-side notification management:
- `getNotifications()` - Fetch unread notifications
- `getAllNotifications()` - Fetch notification history
- `getUnreadNotificationCount()` - Get badge count
- `markNotificationAsRead(id)` - Mark single as read
- `markAllNotificationsAsRead()` - Mark all as read
- `deleteNotification(id)` - Delete notification
- `checkDeadlineNotifications()` - Check and create deadline notifications
### 3. **Notification Component** (`components/views/dashboard/notification-bar.tsx`)
Beautiful notification UI dropdown with:
- Bell icon with unread count badge
- Notification list with type-specific icons and colors
- Action buttons (mark as read, delete)
- Time formatting (e.g., "2m ago")
- Empty state
- Auto-refresh every 30 seconds when open
- Daily deadline check
### 4. **useNotifications Hook** (`hooks/useNotifications.ts`)
Custom React hook wrapping Sonner toast + persistent notifications:
- `notifySuccess()` - Green success toast + persistent notification
- `notifyError()` - Red error toast + persistent notification
- `notifyWarning()` - Yellow warning toast + persistent notification
- `notifyInfo()` - Blue info toast + persistent notification
- `notifyDeadline()` - Red deadline toast + persistent notification
## Integration Points
### 1. **Contract Actions** (`lib/actions/contract.action.ts`)
Updated to create notifications on:
- â
**Upload**: "Contract uploaded successfully"
- â
**Analysis**: "Contract analyzed successfully" or error message
- â
**Delete**: "Contract deleted successfully"
- â
**Ask Question**: Error notification if Q&A fails
### 2. **Dashboard** (`app/(dashboard)/dashboard/page.tsx`)
- Calls `checkDeadlineNotifications()` on page load
- Checks for contracts expiring in 30, 15, 7 days
- Creates notifications automatically
### 3. **Navigation** (`components/views/dashboard/navigation.tsx`)
- Added `NotificationBar` component to sidebar
- Positioned next to theme toggle in account section
- Accessible from all dashboard pages
## Usage Examples
### Creating a Notification in Server Actions
```typescript
import { NotificationService } from "@/lib/services/notification.service";
// In a server action
const user = await ContractService.getUserByClerkId(clerkId);
await NotificationService.create({
userId: user.id,
type: "SUCCESS",
title: "Contract Uploaded",
message: 'Your file "insurance.pdf" is ready for analysis',
contractId: contractId,
actionType: "UPLOAD_SUCCESS",
icon: "FileCheck",
expiresIn: 7 * 24 * 60 * 60 * 1000, // 7 days
});
```
### Using Toast Notifications in Client Components
```typescript
import { useNotifications } from "@/hooks/useNotifications";
export function MyComponent() {
const { notifySuccess, notifyError, notifyDeadline } = useNotifications();
const handleUpload = async () => {
try {
await uploadFile();
notifySuccess("Upload Complete", "Your file has been uploaded");
} catch (error) {
notifyError("Upload Failed", error.message);
}
};
const handleDeadline = () => {
notifyDeadline({
title: "đ´ Contract Expiring Soon",
message: "Insurance Auto from ACME expires in 7 days",
contractId: "contract123",
actionType: "RENEWAL_URGENT",
});
};
return (
<>
>
);
}
```
## Notification Types
### SUCCESS (Green - â
)
Used for:
- Contract uploaded
- Analysis completed
- Contract deleted
- Settings saved
### ERROR (Red - â)
Used for:
- Upload failed
- Analysis failed
- Network errors
- Invalid contract
### WARNING (Yellow - â ī¸)
Used for:
- File analysis slow
- Low quality extraction
- Missing permissions
### INFO (Blue - âšī¸)
Used for:
- Analysis started
- Processing updates
- General information
### DEADLINE (Red - đ)
Used for:
- Contract expiring in 30 days (CRITICAL đ´)
- Contract expiring in 15 days (WARNING đ )
- Contract expiring in 7 days (URGENT đĄ)
## Scheduled Tasks
### Daily Deadline Check
The system checks for upcoming deadlines:
- **When**: Daily at any time (triggered on dashboard load)
- **What**: Scans all user contracts with endDate
- **Actions**:
- Creates CRITICAL notification for 30-day threshold
- Creates WARNING notification for 15-day threshold
- Creates URGENT notification for 7-day threshold
- Avoids duplicate notifications (max 1 per threshold per day)
### Running Deadline Checks Manually
```typescript
import { checkDeadlineNotifications } from "@/lib/actions/notification.action";
// Client-side
const result = await checkDeadlineNotifications();
console.log(`Created ${result.data.count} deadline notifications`);
```
### Cleanup Task (Recommended)
For production, set up a cron job to clean expired notifications:
```typescript
import { NotificationService } from "@/lib/services/notification.service";
// Example: Vercel Cron (serverless function every day at midnight)
export async function GET(request: Request) {
const authHeader = request.headers.get("authorization");
if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response("Unauthorized", { status: 401 });
}
const result = await NotificationService.cleanupExpired();
return Response.json(result);
}
// Route: api/cron/cleanup-notifications
// Set Cron Job: 0 0 * * * (daily at midnight)
```
## Configurable Parameters
### Default Notification Expiration
```typescript
// In NotificationService.create()
const expiresAt = input.expiresIn
? new Date(Date.now() + input.expiresIn)
: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000); // 30 days default
```
### Deadline Thresholds
Located in `NotificationService.checkUpcomingDeadlines()`:
- 30 days: CRITICAL level
- 15 days: WARNING level
- 7 days: URGENT level
To modify, edit these lines in `notification.service.ts`:
```typescript
if (daysUntilExpiration === 7) {
/* ... */
} else if (daysUntilExpiration === 15) {
/* ... */
} else if (daysUntilExpiration === 30) {
/* ... */
}
```
### Notification Bar Polling
```typescript
// In notification-bar.tsx
const pollInterval = setInterval(fetchNotifications, 30000); // 30 seconds
const dailyCheckInterval = setInterval(
() => {
checkDeadlineNotifications();
},
24 * 60 * 60 * 1000,
); // 24 hours
```
## Security & Authorization
All notification operations include authorization checks:
1. **User Verification**: Each action verifies the user owns the notification
2. **Contract Ownership**: Deadline checks only process user's contracts
3. **Input Validation**: Notification content isn't sanitized (all text)
4. **Server-Side Enforcement**: All operations run server-side (no client-side manipulation)
## Troubleshooting
### Migrations Don't Apply
```bash
# Reset migrations (for development only)
npx prisma migrate reset
# Or manually apply pending migrations
npx prisma migrate deploy
```
### Notifications Not Showing
1. Check database connection
2. Verify user exists in User table
3. Check browser console for errors
4. Verify `checkDeadlineNotifications` was called
### Deadline Notifications Not Triggering
1. Ensure contract has `endDate` set
2. Verify contract status is "COMPLETED"
3. Check date calculation (today at midnight)
4. Run manual check: `await checkDeadlineNotifications()`
## Future Enhancements
Potential improvements:
1. **Email Notifications**: Send deadline alerts via email
2. **Batch Operations**: Bulk mark/delete notifications
3. **Notification Preferences**: Let users disable certain types
4. **Snooze Feature**: Temporarily hide notifications
5. **Advanced Filtering**: Filter by type, date range, contract
6. **Export History**: Download notification log as CSV
7. **Push Notifications**: Web/mobile push for critical alerts
8. **Recurring Reminders**: Repeat deadline notifications if ignored
## Support
For issues or questions:
1. Check the notification service comments for implementation details
2. Review contracts-list.tsx for toast integration examples
3. Check notification-bar.tsx for UI implementation
4. See hooks/useNotifications.ts for hook usage