feat: Add AI Assistance Portal components and enhance layout; update notification service and processing pipeline for improved request handling
This commit is contained in:
42
src/App.tsx
42
src/App.tsx
@@ -2894,7 +2894,7 @@ function PortalsPage() {
|
|||||||
return (
|
return (
|
||||||
<PageShell title="Staff & Partner Portals" icon={Building2} eyebrow="Secure access for team members">
|
<PageShell title="Staff & Partner Portals" icon={Building2} eyebrow="Secure access for team members">
|
||||||
<div className="max-w-4xl mx-auto">
|
<div className="max-w-4xl mx-auto">
|
||||||
<div className="grid gap-8 md:grid-cols-3">
|
<div className="grid gap-8 md:grid-cols-2 xl:grid-cols-4">
|
||||||
{/* Admin Portal */}
|
{/* Admin Portal */}
|
||||||
<motion.div
|
<motion.div
|
||||||
className="card bg-gradient-to-br from-red-50 to-rose-50 dark:from-red-900/20 dark:to-rose-900/20 border-red-200 dark:border-red-800"
|
className="card bg-gradient-to-br from-red-50 to-rose-50 dark:from-red-900/20 dark:to-rose-900/20 border-red-200 dark:border-red-800"
|
||||||
@@ -3014,6 +3014,46 @@ function PortalsPage() {
|
|||||||
Access Resource Portal
|
Access Resource Portal
|
||||||
</a>
|
</a>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
{/* AI Assistance Portal - Phase 3 */}
|
||||||
|
<motion.div
|
||||||
|
className="card bg-gradient-to-br from-purple-50 to-violet-50 dark:from-purple-900/20 dark:to-violet-900/20 border-purple-200 dark:border-purple-800"
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ delay: 0.4 }}
|
||||||
|
>
|
||||||
|
<div className="text-center mb-6">
|
||||||
|
<div className="mx-auto w-16 h-16 bg-purple-600 text-white rounded-xl flex items-center justify-center mb-4">
|
||||||
|
<Brain className="h-8 w-8" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-semibold text-purple-900 dark:text-purple-100">AI Assistance Portal</h3>
|
||||||
|
<p className="text-sm text-purple-700 dark:text-purple-300 mt-2">
|
||||||
|
AI-powered request matching and insights
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2 text-sm text-purple-800 dark:text-purple-200 mb-6">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Cpu className="h-4 w-4" />
|
||||||
|
<span>Real-time AI request processing</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Target className="h-4 w-4" />
|
||||||
|
<span>Smart resource matching & allocation</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Activity className="h-4 w-4" />
|
||||||
|
<span>Predictive analytics & insights</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="#/ai-portal"
|
||||||
|
className="block w-full text-center bg-purple-600 text-white py-3 px-4 rounded-lg hover:bg-purple-700 transition-colors font-medium focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
|
||||||
|
>
|
||||||
|
Access AI Portal
|
||||||
|
</a>
|
||||||
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Access Information */}
|
{/* Access Information */}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class MockQueue<T> {
|
|||||||
return job
|
return job
|
||||||
}
|
}
|
||||||
|
|
||||||
process(jobType: string, concurrency: number, processor: (job: { id: string; data: T }) => Promise<void>): void {
|
process(jobType: string, _concurrency: number, processor: (job: { id: string; data: T }) => Promise<void>): void {
|
||||||
this.processors.set(jobType, processor)
|
this.processors.set(jobType, processor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,17 +66,17 @@ class NotificationService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async notifyStudent(studentId: string, assignment: any): Promise<void> {
|
async notifyStudent(studentId: string, _assignment: any): Promise<void> {
|
||||||
console.log(`📧 Notifying student ${studentId} about assignment`)
|
console.log(`📧 Notifying student ${studentId} about assignment`)
|
||||||
// In production: send email, SMS, or push notification
|
// In production: send email, SMS, or push notification
|
||||||
}
|
}
|
||||||
|
|
||||||
async notifyVolunteer(volunteerId: string, assignment: any): Promise<void> {
|
async notifyVolunteer(volunteerId: string, _assignment: any): Promise<void> {
|
||||||
console.log(`📧 Notifying volunteer ${volunteerId} about new assignment`)
|
console.log(`📧 Notifying volunteer ${volunteerId} about new assignment`)
|
||||||
// In production: send volunteer notification
|
// In production: send volunteer notification
|
||||||
}
|
}
|
||||||
|
|
||||||
async notifyCoordinators(assignment: any): Promise<void> {
|
async notifyCoordinators(_assignment: any): Promise<void> {
|
||||||
console.log(`📧 Notifying coordinators about new assignment`)
|
console.log(`📧 Notifying coordinators about new assignment`)
|
||||||
// In production: alert coordination team
|
// In production: alert coordination team
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ class NotificationService {
|
|||||||
// In production: trigger donor engagement campaign
|
// In production: trigger donor engagement campaign
|
||||||
}
|
}
|
||||||
|
|
||||||
async notifyReviewer(reviewer: any, reviewTask: any, aiInsights: any): Promise<void> {
|
async notifyReviewer(reviewer: any, _reviewTask: any, aiInsights: any): Promise<void> {
|
||||||
console.log(`👥 Notifying reviewer ${reviewer.id} about review task with AI confidence: ${aiInsights.aiConfidence}`)
|
console.log(`👥 Notifying reviewer ${reviewer.id} about review task with AI confidence: ${aiInsights.aiConfidence}`)
|
||||||
// In production: send detailed review notification with AI recommendations
|
// In production: send detailed review notification with AI recommendations
|
||||||
}
|
}
|
||||||
@@ -303,7 +303,7 @@ export class RealTimeProcessingPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async selectOptimalReviewer(request: StudentRequest, matches: MatchResult[]) {
|
private async selectOptimalReviewer(request: StudentRequest, _matches: MatchResult[]) {
|
||||||
// Mock reviewer selection - in production, this would use actual staff data
|
// Mock reviewer selection - in production, this would use actual staff data
|
||||||
const reviewers = [
|
const reviewers = [
|
||||||
{ id: 'rev1', name: 'Sarah Martinez', specialties: ['clothing', 'emergency-housing'], workload: 5 },
|
{ id: 'rev1', name: 'Sarah Martinez', specialties: ['clothing', 'emergency-housing'], workload: 5 },
|
||||||
@@ -366,7 +366,7 @@ export class RealTimeProcessingPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateDashboard(requestId: string, matches: MatchResult[]): Promise<void> {
|
private async updateDashboard(requestId: string, _matches: MatchResult[]): Promise<void> {
|
||||||
console.log(`📊 Updating dashboard for request ${requestId}`)
|
console.log(`📊 Updating dashboard for request ${requestId}`)
|
||||||
// In production: update real-time analytics dashboard
|
// In production: update real-time analytics dashboard
|
||||||
}
|
}
|
||||||
@@ -387,7 +387,7 @@ export class RealTimeProcessingPipeline {
|
|||||||
await this.routeForHumanReview(request, [])
|
await this.routeForHumanReview(request, [])
|
||||||
}
|
}
|
||||||
|
|
||||||
private async trackDecision(request: StudentRequest, match: MatchResult, decision: string): Promise<void> {
|
private async trackDecision(request: StudentRequest, _match: MatchResult, decision: string): Promise<void> {
|
||||||
console.log(`📈 Tracking decision: ${decision} for request ${request.id}`)
|
console.log(`📈 Tracking decision: ${decision} for request ${request.id}`)
|
||||||
// In production: log decision for ML model training
|
// In production: log decision for ML model training
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -531,7 +531,7 @@ export class StudentAssistanceAI {
|
|||||||
return candidates.map(candidate => this.calculateRuleBasedScore(candidate, analysis, request))
|
return candidates.map(candidate => this.calculateRuleBasedScore(candidate, analysis, request))
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateRuleBasedScore(candidate: any, analysis: RequestAnalysis, request: StudentRequest): MatchResult {
|
private calculateRuleBasedScore(candidate: any, analysis: RequestAnalysis, _request: StudentRequest): MatchResult {
|
||||||
let score = 0.5 // Base score
|
let score = 0.5 // Base score
|
||||||
|
|
||||||
// Category match bonus
|
// Category match bonus
|
||||||
@@ -581,7 +581,7 @@ export class StudentAssistanceAI {
|
|||||||
estimatedCost: candidate.avgCost,
|
estimatedCost: candidate.avgCost,
|
||||||
fulfillmentTimeline: this.estimateTimeline(analysis.urgencyScore, analysis.complexityEstimate),
|
fulfillmentTimeline: this.estimateTimeline(analysis.urgencyScore, analysis.complexityEstimate),
|
||||||
reasoningFactors: this.generateReasoningFactors(candidate, analysis),
|
reasoningFactors: this.generateReasoningFactors(candidate, analysis),
|
||||||
riskFactors: this.identifyRiskFactors(candidate, analysis, request)
|
riskFactors: this.identifyRiskFactors(candidate, analysis)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -465,7 +465,7 @@ function ConfidenceIndicator({ confidence }: { confidence: number }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function AIPerformanceMetrics() {
|
function AIPerformanceMetrics() {
|
||||||
const [metrics, setMetrics] = useState<AIMetrics>({
|
const [metrics] = useState<AIMetrics>({
|
||||||
accuracyRate: 0.87,
|
accuracyRate: 0.87,
|
||||||
accuracyTrend: 2.3,
|
accuracyTrend: 2.3,
|
||||||
avgProcessingTime: 1.8,
|
avgProcessingTime: 1.8,
|
||||||
|
|||||||
@@ -49,6 +49,26 @@
|
|||||||
@apply text-sm font-medium text-neutral-600 transition hover:text-primary-600 dark:text-neutral-300 dark:hover:text-primary-400;
|
@apply text-sm font-medium text-neutral-600 transition hover:text-primary-600 dark:text-neutral-300 dark:hover:text-primary-400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Form Components */
|
||||||
|
.input-field {
|
||||||
|
@apply w-full rounded-xl border border-gray-300 bg-white px-4 py-3 text-sm text-gray-900 placeholder-gray-500 transition focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-400 dark:focus:border-primary-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text Utilities */
|
||||||
|
.line-clamp-2 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-clamp-3 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 3;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
@apply w-full rounded-xl border border-white/30 bg-white/70 px-3 py-2 text-sm backdrop-blur transition focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20 dark:border-white/10 dark:bg-white/10 dark:focus:border-primary-400;
|
@apply w-full rounded-xl border border-white/30 bg-white/70 px-3 py-2 text-sm backdrop-blur transition focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20 dark:border-white/10 dark:bg-white/10 dark:focus:border-primary-400;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user