Files
pfm/PostFundManagement.ShowcaseUI/src/components/partner/PartnerShowcase.tsx
T
2026-10-29 17:40:48 +02:00

213 lines
11 KiB
TypeScript

import React, { useState } from 'react';
import {
FileCheck2,
UploadCloud,
MessageSquare,
KeyRound,
CheckCircle,
Clock,
ShieldAlert,
ExternalLink,
Maximize2,
FileSignature
} from 'lucide-react';
import { SCREENSHOTS, ScreenshotItem } from '../../data/showcaseData';
interface PartnerShowcaseProps {
onOpenScreenshot: (item: ScreenshotItem) => void;
}
export const PartnerShowcase: React.FC<PartnerShowcaseProps> = ({ onOpenScreenshot }) => {
const partnerScreenshots = SCREENSHOTS.filter((s) => s.platform === 'PFM Partner');
const [selectedCategory, setSelectedCategory] = useState<string>('All');
const categories = ['All', 'Dashboard', 'Evidence & Proof', 'Communications', 'Onboarding'];
const filteredScreens = selectedCategory === 'All'
? partnerScreenshots
: partnerScreenshots.filter((s) => s.category === selectedCategory);
return (
<section id="partner-section" className="py-24 bg-slate-950 relative border-t border-slate-900 overflow-hidden">
{/* Background ambient glow */}
<div className="absolute top-1/4 right-0 w-96 h-96 bg-emerald-600/10 blur-[140px] rounded-full pointer-events-none -z-10" />
<div className="absolute bottom-10 left-0 w-80 h-80 bg-teal-600/10 blur-[130px] rounded-full pointer-events-none -z-10" />
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{/* Section Header */}
<div className="flex flex-col md:flex-row md:items-end justify-between gap-6 mb-16">
<div className="max-w-3xl">
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-emerald-500/10 border border-emerald-500/30 text-emerald-400 text-xs font-semibold mb-4">
<FileCheck2 className="w-3.5 h-3.5" />
<span>Grantee & Implementing Partner Suite</span>
</div>
<h2 className="text-3xl sm:text-4xl font-extrabold text-white tracking-tight leading-tight">
PFM Partner •{' '}
<span className="text-transparent bg-clip-text bg-gradient-to-r from-emerald-400 via-teal-400 to-cyan-400">
Field Delivery & Evidence Hub
</span>
</h2>
<p className="mt-3 text-base text-slate-300 leading-relaxed">
Empower implementing teams to manage sanctioned grant agreements, execute work-breakdown activities, and upload tamper-evident proofs directly against funding covenants.
</p>
</div>
<div className="flex items-center gap-3">
<a
href="https://partner.ifri.khongisa.co.za"
target="_blank"
rel="noreferrer"
className="px-4 py-2 rounded-xl bg-emerald-600/20 hover:bg-emerald-600/30 border border-emerald-500/40 text-emerald-300 hover:text-white text-xs font-semibold transition-all flex items-center gap-2 shadow-sm"
>
<span>Launch Live Partner Portal</span>
<ExternalLink className="w-3.5 h-3.5" />
</a>
</div>
</div>
{/* 3 Core Partner Pillars */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-16">
{/* Pillar 1 */}
<div className="p-6 rounded-2xl bg-slate-900/60 border border-slate-800/80 hover:border-emerald-500/40 transition-all shadow-xl group">
<div className="w-12 h-12 rounded-xl bg-emerald-500/10 border border-emerald-500/20 flex items-center justify-center text-emerald-400 mb-5 group-hover:scale-110 transition-transform">
<UploadCloud className="w-6 h-6" />
</div>
<div className="flex items-center gap-2 mb-2">
<span className="text-xs font-mono font-semibold text-emerald-400">PILLAR 01</span>
<span className="text-slate-600">•</span>
<span className="text-xs text-slate-400">Evidence Vault</span>
</div>
<h3 className="text-lg font-bold text-white mb-2">
Granular Activity Proof Uploads
</h3>
<p className="text-xs text-slate-300 leading-relaxed mb-4">
Attach statutory documents, invoices, and geotagged photographs directly to milestones with pre-signed S3 storage and immediate SHA verification.
</p>
<div className="pt-4 border-t border-slate-800/80 flex items-center justify-between text-[11px] text-slate-400">
<span className="font-mono text-emerald-400 font-semibold">100% Traceable</span>
<span>Garage S3 Vault</span>
</div>
</div>
{/* Pillar 2 */}
<div className="p-6 rounded-2xl bg-slate-900/60 border border-slate-800/80 hover:border-teal-500/40 transition-all shadow-xl group">
<div className="w-12 h-12 rounded-xl bg-teal-500/10 border border-teal-500/20 flex items-center justify-center text-teal-400 mb-5 group-hover:scale-110 transition-transform">
<MessageSquare className="w-6 h-6" />
</div>
<div className="flex items-center gap-2 mb-2">
<span className="text-xs font-mono font-semibold text-teal-400">PILLAR 02</span>
<span className="text-slate-600">•</span>
<span className="text-xs text-slate-400">Direct Comms</span>
</div>
<h3 className="text-lg font-bold text-white mb-2">
Direct Programme Officer Comms
</h3>
<p className="text-xs text-slate-300 leading-relaxed mb-4">
Eliminate lost email chains. Built-in contextual messaging links every query, revision request, and milestone note directly into an auditable project thread.
</p>
<div className="pt-4 border-t border-slate-800/80 flex items-center justify-between text-[11px] text-slate-400">
<span className="font-mono text-teal-400 font-semibold">Direct Inbox</span>
<span>Audit Logged</span>
</div>
</div>
{/* Pillar 3 */}
<div className="p-6 rounded-2xl bg-slate-900/60 border border-slate-800/80 hover:border-cyan-500/40 transition-all shadow-xl group">
<div className="w-12 h-12 rounded-xl bg-cyan-500/10 border border-cyan-500/20 flex items-center justify-center text-cyan-400 mb-5 group-hover:scale-110 transition-transform">
<KeyRound className="w-6 h-6" />
</div>
<div className="flex items-center gap-2 mb-2">
<span className="text-xs font-mono font-semibold text-cyan-400">PILLAR 03</span>
<span className="text-slate-600">•</span>
<span className="text-xs text-slate-400">Rapid Mobilization</span>
</div>
<h3 className="text-lg font-bold text-white mb-2">
Statutory SSO Onboarding & Tranches
</h3>
<p className="text-xs text-slate-300 leading-relaxed mb-4">
Single-token statutory onboarding invitations allow instant portal mobilization, KYC compliance verification, and clear visibility into covenant-tied tranches.
</p>
<div className="pt-4 border-t border-slate-800/80 flex items-center justify-between text-[11px] text-slate-400">
<span className="font-mono text-cyan-400 font-semibold">Zero Friction</span>
<span>Duende STS Auth</span>
</div>
</div>
</div>
{/* Screenshot Category Filter & Grid */}
<div className="mb-6 flex flex-wrap items-center justify-between gap-4">
<div className="flex items-center gap-2 p-1 rounded-xl bg-slate-900 border border-slate-800">
{categories.map((cat) => (
<button
key={cat}
onClick={() => setSelectedCategory(cat)}
className={`px-3 py-1.5 rounded-lg text-xs font-semibold transition-all ${
selectedCategory === cat
? 'bg-emerald-600 text-white shadow-sm'
: 'text-slate-400 hover:text-slate-200'
}`}
>
{cat}
</button>
))}
</div>
<span className="text-xs text-slate-400 font-mono">
Showing {filteredScreens.length} Partner Views
</span>
</div>
{/* Screenshot Cards Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{filteredScreens.map((screen) => (
<div
key={screen.id}
onClick={() => onOpenScreenshot(screen)}
className="group cursor-pointer rounded-2xl bg-slate-900/60 border border-slate-800 hover:border-emerald-500/50 overflow-hidden shadow-xl transition-all duration-300 hover:-translate-y-1"
>
<div className="relative aspect-[16/10] overflow-hidden bg-slate-950">
<img
src={screen.image}
alt={screen.title}
className="w-full h-full object-cover object-top group-hover:scale-105 transition-transform duration-500"
loading="lazy"
/>
<div className="absolute inset-0 bg-gradient-to-t from-slate-950 via-slate-950/20 to-transparent opacity-80 group-hover:opacity-40 transition-opacity" />
<div className="absolute top-3 right-3 p-2 rounded-lg bg-slate-950/80 backdrop-blur-md border border-slate-700/80 text-slate-300 opacity-0 group-hover:opacity-100 transition-opacity">
<Maximize2 className="w-4 h-4" />
</div>
<div className="absolute bottom-3 left-3">
<span className="text-[10px] uppercase font-bold tracking-wider px-2.5 py-1 rounded-full bg-emerald-500/20 text-emerald-300 border border-emerald-500/30 backdrop-blur-md">
{screen.category}
</span>
</div>
</div>
<div className="p-5">
<h4 className="text-base font-bold text-white mb-1 group-hover:text-emerald-300 transition-colors">
{screen.title}
</h4>
<p className="text-xs text-slate-300 leading-relaxed mb-4 line-clamp-2">
{screen.description}
</p>
<div className="flex flex-wrap gap-1.5">
{screen.tags.map((tag) => (
<span
key={tag}
className="text-[10px] font-mono px-2 py-0.5 rounded bg-slate-800/80 text-slate-400"
>
#{tag}
</span>
))}
</div>
</div>
</div>
))}
</div>
</div>
</section>
);
};