modcomms/frontend/components/Profile.tsx
michael 0fdaedc7ff Complete UI design system migration to Barclays brand colors
Updates all remaining frontend components to use the new Barclays
design system color tokens:
- brand-dark-blue → primary-blue (#1A2142)
- brand-accent → active-blue (#006DE3)
- brand-light-blue → cyan-brand (#00AEEF)
- brand-gray → grey-100 (#F6F6F6)

Components updated:
- CampaignDetail and ProofDetailView in Campaigns.tsx
- Projects.tsx (full component migration)
- StatusDashboard.tsx (status tiles and colors)
- CreateProjectModal.tsx (modal styling)
- FeedbackReport.tsx (remaining brand colors)
- Login.tsx and Profile.tsx
- WIPReviewer.tsx and CopyGenAI.tsx
- Header, LoadingVisual, ToggleSwitch
- AssetPreview, ProofPreview, AssetUpload
- ProofTypeManager

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 14:00:13 -06:00

156 lines
No EOL
7.7 KiB
TypeScript
Executable file

import React, { useState, useEffect } from 'react';
import { IPublicClientApplication } from '@azure/msal-browser';
import { LogoutIcon } from './icons/LogoutIcon';
import { QuestionMarkIcon } from './icons/QuestionMarkIcon';
import { getUserInfo, UserInfo } from '../services/authService';
import { apiService } from '../services/apiService';
interface ProfileProps {
onLogout: () => void;
msalInstance: IPublicClientApplication;
}
export const Profile: React.FC<ProfileProps> = ({ onLogout, msalInstance }) => {
const [isQuestionFormVisible, setIsQuestionFormVisible] = useState(false);
const [question, setQuestion] = useState('');
const [userInfo, setUserInfo] = useState<UserInfo | null>(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitStatus, setSubmitStatus] = useState<{ type: 'success' | 'error'; message: string } | null>(null);
useEffect(() => {
const info = getUserInfo(msalInstance);
setUserInfo(info);
}, [msalInstance]);
const userDetails = userInfo ? {
'Account Type': userInfo.accountType,
'First Name': userInfo.firstName || 'N/A',
'Last Name': userInfo.lastName || 'N/A',
'Email': userInfo.email,
} : {
'Account Type': 'Loading...',
'First Name': '',
'Last Name': '',
'Email': '',
};
const handleLogout = () => {
onLogout();
};
const handleToggleQuestionForm = () => {
setIsQuestionFormVisible(prev => !prev);
};
const handleSubmitQuestion = async (e: React.FormEvent) => {
e.preventDefault();
if (!question.trim()) {
setSubmitStatus({ type: 'error', message: 'Please enter a question before submitting.' });
return;
}
setIsSubmitting(true);
setSubmitStatus(null);
try {
await apiService.sendSupportEmail({
message: question,
subject: 'Question from Mod Comms User',
user_name: userInfo ? `${userInfo.firstName} ${userInfo.lastName}`.trim() : undefined,
user_email: userInfo?.email,
});
setSubmitStatus({ type: 'success', message: 'Your question has been submitted. We\'ll get back to you shortly.' });
setQuestion('');
setTimeout(() => {
setIsQuestionFormVisible(false);
setSubmitStatus(null);
}, 3000);
} catch (error) {
setSubmitStatus({ type: 'error', message: 'Failed to submit question. Please try again later.' });
} finally {
setIsSubmitting(false);
}
};
return (
<div className="p-4 sm:p-6 lg:p-8 h-full bg-grey-100">
<header className="mb-8">
<h1 className="text-3xl lg:text-4xl font-bold text-primary-blue">Your Profile</h1>
<p className="text-base lg:text-lg text-gray-600 mt-1">View your account details and manage settings.</p>
</header>
<div className="max-w-3xl">
<section className="bg-white rounded-lg shadow-md p-6 sm:p-8 border border-gray-200">
<h2 className="text-2xl font-bold text-primary-blue mb-6">Account Information</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-x-8 gap-y-5">
{Object.entries(userDetails).map(([key, value]) => (
<div key={key}>
<p className="text-sm font-semibold text-gray-500 tracking-wide uppercase">{key}</p>
<p className="text-lg text-gray-800 mt-1">{value}</p>
</div>
))}
</div>
<div className="border-t border-gray-200 mt-8 pt-6 flex flex-col sm:flex-row gap-3">
<button
onClick={handleLogout}
className="flex items-center justify-center gap-2 bg-red-600 text-white font-semibold py-2 px-4 rounded-md hover:bg-red-700 transition-colors duration-300"
>
<LogoutIcon className="h-5 w-5" />
Logout
</button>
<button
onClick={handleToggleQuestionForm}
className="flex items-center justify-center gap-2 bg-gray-200 text-gray-800 font-semibold py-2 px-4 rounded-md hover:bg-gray-300 transition-colors duration-300"
>
<QuestionMarkIcon className="h-5 w-5" />
Got a question?
</button>
</div>
</section>
{isQuestionFormVisible && (
<section className="mt-8 bg-white rounded-lg shadow-md p-6 sm:p-8 border border-gray-200">
<h2 className="text-2xl font-bold text-primary-blue mb-4">Ask a Question</h2>
<form onSubmit={handleSubmitQuestion}>
<p className="text-gray-600 mb-4">Your question will be sent to the OLIVER Agency support team.</p>
{submitStatus && (
<div className={`mb-4 p-3 rounded-md ${submitStatus.type === 'success' ? 'bg-green-50 text-green-700 border border-green-200' : 'bg-red-50 text-red-700 border border-red-200'}`}>
{submitStatus.message}
</div>
)}
<textarea
value={question}
onChange={(e) => setQuestion(e.target.value)}
className="w-full p-3 border border-gray-300 rounded-md focus:ring-2 focus:ring-active-blue focus:border-active-blue transition"
placeholder="Type your question here..."
rows={5}
required
disabled={isSubmitting}
/>
<div className="mt-4 flex justify-end">
<button
type="submit"
className="bg-active-blue text-white font-semibold py-2 px-5 rounded-md hover:bg-primary-blue transition-colors duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed flex items-center gap-2"
disabled={!question.trim() || isSubmitting}
>
{isSubmitting ? (
<>
<svg className="animate-spin h-4 w-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Submitting...
</>
) : (
'Submit Question'
)}
</button>
</div>
</form>
</section>
)}
</div>
</div>
);
};