fix issues
This commit is contained in:
@@ -23,6 +23,11 @@ export function TwoFactorAuth({ onLogin, onNavigate }: TwoFactorAuthProps) {
|
||||
|
||||
const otpRefs = useRef<(HTMLInputElement | null)[]>([]);
|
||||
|
||||
// Initialize refs array
|
||||
useEffect(() => {
|
||||
otpRefs.current = otpRefs.current.slice(0, 6);
|
||||
}, []);
|
||||
|
||||
// Get masked email from login context
|
||||
useEffect(() => {
|
||||
const loginContext = sessionStorage.getItem('login_context');
|
||||
@@ -30,7 +35,6 @@ export function TwoFactorAuth({ onLogin, onNavigate }: TwoFactorAuthProps) {
|
||||
const { email } = JSON.parse(loginContext);
|
||||
setMaskedEmail(email);
|
||||
} else {
|
||||
// Fallback masked email if no context
|
||||
setMaskedEmail('ad***@klc.edu');
|
||||
}
|
||||
}, []);
|
||||
@@ -43,11 +47,14 @@ export function TwoFactorAuth({ onLogin, onNavigate }: TwoFactorAuthProps) {
|
||||
}
|
||||
}, [resendCooldown]);
|
||||
|
||||
// Focus management - focus first input on mount
|
||||
// Focus first input on mount
|
||||
useEffect(() => {
|
||||
if (otpRefs.current[0]) {
|
||||
otpRefs.current[0].focus();
|
||||
}
|
||||
const timer = setTimeout(() => {
|
||||
if (otpRefs.current[0]) {
|
||||
otpRefs.current[0].focus();
|
||||
}
|
||||
}, 100);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
const handleVerifyCode = async (e: React.FormEvent) => {
|
||||
@@ -62,21 +69,15 @@ export function TwoFactorAuth({ onLogin, onNavigate }: TwoFactorAuthProps) {
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
// Simulate API call with different scenarios
|
||||
setTimeout(() => {
|
||||
if (code === '000000') {
|
||||
// Simulate expired code
|
||||
setError('Code expired. Request a new one.');
|
||||
} else if (code === '999999') {
|
||||
// Simulate too many attempts
|
||||
setError('Too many attempts. Please wait before retrying.');
|
||||
} else if (code === '123456') {
|
||||
// Successful verification
|
||||
// Clear session storage and redirect to dashboard
|
||||
sessionStorage.removeItem('login_context');
|
||||
onLogin();
|
||||
} else {
|
||||
// Incorrect code
|
||||
const newAttempts = attempts + 1;
|
||||
setAttempts(newAttempts);
|
||||
|
||||
@@ -86,7 +87,6 @@ export function TwoFactorAuth({ onLogin, onNavigate }: TwoFactorAuthProps) {
|
||||
setError('Incorrect code.');
|
||||
}
|
||||
|
||||
// Clear the code inputs and focus first input
|
||||
setVerificationCode(['', '', '', '', '', '']);
|
||||
if (otpRefs.current[0]) {
|
||||
otpRefs.current[0].focus();
|
||||
@@ -96,53 +96,85 @@ export function TwoFactorAuth({ onLogin, onNavigate }: TwoFactorAuthProps) {
|
||||
}, 1200);
|
||||
};
|
||||
|
||||
const handleCodeInput = (index: number, value: string) => {
|
||||
const handleCodeChange = (index: number, value: string) => {
|
||||
// Clear errors when user starts typing
|
||||
if (error) {
|
||||
setError('');
|
||||
}
|
||||
|
||||
// Handle paste - distribute "123456" across all inputs
|
||||
if (value.length > 1) {
|
||||
const pastedCode = value.slice(0, 6).split('');
|
||||
const newCode = [...verificationCode];
|
||||
|
||||
pastedCode.forEach((char, i) => {
|
||||
if (index + i < 6 && /^\d$/.test(char)) {
|
||||
newCode[index + i] = char;
|
||||
}
|
||||
});
|
||||
|
||||
setVerificationCode(newCode);
|
||||
|
||||
// Focus the last filled input or the next empty one
|
||||
const lastIndex = Math.min(index + pastedCode.length - 1, 5);
|
||||
const nextEmptyIndex = newCode.findIndex((char, i) => i > lastIndex && char === '');
|
||||
const focusIndex = nextEmptyIndex !== -1 ? nextEmptyIndex : lastIndex;
|
||||
|
||||
if (otpRefs.current[focusIndex]) {
|
||||
otpRefs.current[focusIndex]?.focus();
|
||||
}
|
||||
// Only allow digits
|
||||
if (value && !/^\d+$/.test(value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle single character input (digits only)
|
||||
if (/^\d$/.test(value) || value === '') {
|
||||
// Handle single digit input
|
||||
if (value.length <= 1) {
|
||||
const newCode = [...verificationCode];
|
||||
newCode[index] = value;
|
||||
setVerificationCode(newCode);
|
||||
|
||||
// Auto-advance to next input
|
||||
if (value && index < 5 && otpRefs.current[index + 1]) {
|
||||
otpRefs.current[index + 1]?.focus();
|
||||
// Auto-focus next input if a digit was entered
|
||||
if (value && index < 5) {
|
||||
const nextInput = otpRefs.current[index + 1];
|
||||
if (nextInput) {
|
||||
// Use setTimeout to ensure the state update has happened
|
||||
setTimeout(() => {
|
||||
nextInput.focus();
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleCodeKeyDown = (index: number, e: React.KeyboardEvent) => {
|
||||
// Backspace navigation
|
||||
if (e.key === 'Backspace' && !verificationCode[index] && index > 0) {
|
||||
otpRefs.current[index - 1]?.focus();
|
||||
const handleKeyDown = (index: number, e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
// Handle backspace
|
||||
if (e.key === 'Backspace') {
|
||||
if (!verificationCode[index] && index > 0) {
|
||||
// Move to previous input if current is empty
|
||||
const prevInput = otpRefs.current[index - 1];
|
||||
if (prevInput) {
|
||||
prevInput.focus();
|
||||
}
|
||||
} else if (verificationCode[index]) {
|
||||
// Clear current input but stay focused
|
||||
const newCode = [...verificationCode];
|
||||
newCode[index] = '';
|
||||
setVerificationCode(newCode);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle arrow keys
|
||||
else if (e.key === 'ArrowLeft' && index > 0) {
|
||||
const prevInput = otpRefs.current[index - 1];
|
||||
if (prevInput) {
|
||||
prevInput.focus();
|
||||
}
|
||||
} else if (e.key === 'ArrowRight' && index < 5) {
|
||||
const nextInput = otpRefs.current[index + 1];
|
||||
if (nextInput) {
|
||||
nextInput.focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {
|
||||
e.preventDefault();
|
||||
const pastedData = e.clipboardData.getData('text');
|
||||
const digits = pastedData.replace(/\D/g, '').slice(0, 6).split('');
|
||||
|
||||
if (digits.length === 6) {
|
||||
const newCode = [...verificationCode];
|
||||
digits.forEach((digit, i) => {
|
||||
newCode[i] = digit;
|
||||
});
|
||||
setVerificationCode(newCode);
|
||||
|
||||
// Focus the last input after paste
|
||||
setTimeout(() => {
|
||||
if (otpRefs.current[5]) {
|
||||
otpRefs.current[5].focus();
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -154,25 +186,11 @@ export function TwoFactorAuth({ onLogin, onNavigate }: TwoFactorAuthProps) {
|
||||
setVerificationCode(['', '', '', '', '', '']);
|
||||
|
||||
// Focus first input after resend
|
||||
if (otpRefs.current[0]) {
|
||||
otpRefs.current[0].focus();
|
||||
}
|
||||
|
||||
// Simulate API call
|
||||
setTimeout(() => {
|
||||
// Success handling would go here
|
||||
}, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
const handleFirstInputFocus = () => {
|
||||
// Announce "6 fields" when first input is focused
|
||||
const announcement = document.getElementById('otp-announcement');
|
||||
if (announcement) {
|
||||
announcement.textContent = '6 digit verification code input fields';
|
||||
setTimeout(() => {
|
||||
announcement.textContent = '';
|
||||
}, 2000);
|
||||
if (otpRefs.current[0]) {
|
||||
otpRefs.current[0].focus();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -220,19 +238,23 @@ export function TwoFactorAuth({ onLogin, onNavigate }: TwoFactorAuthProps) {
|
||||
{verificationCode.map((digit, index) => (
|
||||
<Input
|
||||
key={index}
|
||||
ref={(el) => (otpRefs.current[index] = el)}
|
||||
ref={(el) => {
|
||||
otpRefs.current[index] = el;
|
||||
}}
|
||||
type="text"
|
||||
inputMode="numeric"
|
||||
maxLength={6}
|
||||
pattern="[0-9]*"
|
||||
maxLength={1}
|
||||
value={digit}
|
||||
onChange={(e) => handleCodeInput(index, e.target.value)}
|
||||
onKeyDown={(e) => handleCodeKeyDown(index, e)}
|
||||
onFocus={index === 0 ? handleFirstInputFocus : undefined}
|
||||
onChange={(e) => handleCodeChange(index, e.target.value)}
|
||||
onKeyDown={(e) => handleKeyDown(index, e)}
|
||||
onPaste={index === 0 ? handlePaste : undefined}
|
||||
className="w-12 h-12 text-center font-mono text-lg focus-visible:ring-2 focus-visible:ring-[var(--color-brand-primary)] focus-visible:ring-opacity-50"
|
||||
aria-label={`Digit ${index + 1} of 6`}
|
||||
aria-describedby={error ? "code-error" : undefined}
|
||||
aria-invalid={!!error}
|
||||
disabled={tooManyAttempts}
|
||||
autoComplete="one-time-code"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -327,26 +349,6 @@ export function TwoFactorAuth({ onLogin, onNavigate }: TwoFactorAuthProps) {
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* Screen reader announcements */}
|
||||
<div
|
||||
id="otp-announcement"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
aria-label="OTP field information"
|
||||
className="sr-only"
|
||||
/>
|
||||
|
||||
<div
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
aria-label="Form status"
|
||||
className="sr-only"
|
||||
>
|
||||
{isLoading && "Verifying code, please wait"}
|
||||
{error && `Error: ${error}`}
|
||||
{resendCooldown > 0 && `Resend available in ${resendCooldown} seconds`}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
// In ContentManager.tsx - FIXED VERSION
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { AuthenticatedLayout } from "../layout/AuthenticatedLayout";
|
||||
import { Card, CardContent } from "../ui/card";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs";
|
||||
@@ -20,11 +21,13 @@ import { ReadingMaterialsTab } from "./tabs/ReadingMaterialsTab";
|
||||
import { KLCContentArchiveTab } from "./tabs/KLCContentArchiveTab";
|
||||
import { CaseStudiesTab } from "./tabs/CaseStudiesTab";
|
||||
import { PodcastsTab } from "./tabs/PodcastsTab";
|
||||
import { Route } from "../../types/routes";
|
||||
|
||||
interface ContentManagerProps {
|
||||
onNavigate: (route: string) => void;
|
||||
onNavigate: (route: Route) => void;
|
||||
onLogout: () => void;
|
||||
user: any;
|
||||
currentRoute?: Route;
|
||||
}
|
||||
|
||||
const contentTabs = [
|
||||
@@ -43,7 +46,7 @@ const contentTabs = [
|
||||
primaryAction: "New Blog"
|
||||
},
|
||||
{
|
||||
id: "faq",
|
||||
id: "faq", // This is the tab ID - note it's "faq" without 's'
|
||||
label: "FAQ",
|
||||
icon: HelpCircle,
|
||||
canCreate: true,
|
||||
@@ -110,13 +113,79 @@ export function ContentManager({
|
||||
onNavigate,
|
||||
onLogout,
|
||||
user,
|
||||
currentRoute = "/content",
|
||||
}: ContentManagerProps) {
|
||||
const [activeTab, setActiveTab] = useState("profiler");
|
||||
console.log('📦 ContentManager received currentRoute:', currentRoute);
|
||||
|
||||
const getInitialTab = () => {
|
||||
console.log('🔄 getInitialTab called with currentRoute:', currentRoute);
|
||||
|
||||
// Map routes to tab IDs correctly
|
||||
if (currentRoute.includes('/content/blogs')) return 'blogs';
|
||||
if (currentRoute.includes('/content/faqs')) return 'faq'; // This should be 'faq' to match the tab ID
|
||||
if (currentRoute.includes('/content/webcasts')) return 'webcasts';
|
||||
if (currentRoute.includes('/content/training-materials')) return 'training-materials';
|
||||
if (currentRoute.includes('/content/reading-materials')) return 'reading-materials';
|
||||
if (currentRoute.includes('/content/podcasts')) return 'podcasts';
|
||||
if (currentRoute.includes('/content/case-studies')) return 'case-studies';
|
||||
if (currentRoute.includes('/content/klc-content-archive')) return 'klc-content-archive';
|
||||
|
||||
console.log('📌 Defaulting to profiler tab');
|
||||
return 'profiler';
|
||||
};
|
||||
|
||||
const [activeTab, setActiveTab] = useState(getInitialTab());
|
||||
const [activeInnerTab, setActiveInnerTab] = useState<{ [key: string]: string }>({
|
||||
"training-materials": "Facilitator Manual",
|
||||
"klc-content-archive": "Leadership Lego Blocks"
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
console.log('🔄 Route changed, updating active tab. Current route:', currentRoute);
|
||||
const newTab = getInitialTab();
|
||||
console.log('📌 Setting active tab to:', newTab);
|
||||
setActiveTab(newTab);
|
||||
}, [currentRoute]);
|
||||
|
||||
const handleTabChange = (tabId: string) => {
|
||||
console.log('🔄 Tab changed to:', tabId);
|
||||
setActiveTab(tabId);
|
||||
|
||||
// Navigate to specific routes when tabs are clicked
|
||||
switch (tabId) {
|
||||
case 'blogs':
|
||||
onNavigate('/content/blogs');
|
||||
break;
|
||||
case 'faq': // This should be 'faq' to match the tab ID
|
||||
onNavigate('/content/faqs');
|
||||
break;
|
||||
case 'webcasts':
|
||||
onNavigate('/content/webcasts');
|
||||
break;
|
||||
case 'training-materials':
|
||||
onNavigate('/content/training-materials');
|
||||
break;
|
||||
case 'reading-materials':
|
||||
onNavigate('/content/reading-materials');
|
||||
break;
|
||||
case 'podcasts':
|
||||
onNavigate('/content/podcasts');
|
||||
break;
|
||||
case 'case-studies':
|
||||
onNavigate('/content/case-studies');
|
||||
break;
|
||||
case 'klc-content-archive':
|
||||
onNavigate('/content/klc-content-archive');
|
||||
break;
|
||||
default:
|
||||
onNavigate('/content');
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log('📌 Current active tab:', activeTab);
|
||||
}, [activeTab]);
|
||||
|
||||
const breadcrumbs = [
|
||||
{ label: "Content" }
|
||||
];
|
||||
@@ -132,7 +201,6 @@ export function ContentManager({
|
||||
breadcrumbs={breadcrumbs}
|
||||
>
|
||||
<div className="p-6 space-y-6 max-w-[1440px] mx-auto">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1>Content Manager</h1>
|
||||
@@ -142,9 +210,7 @@ export function ContentManager({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Content */}
|
||||
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab}>
|
||||
<Tabs value={activeTab} onValueChange={handleTabChange}>
|
||||
<TabsList className="grid w-full grid-cols-9 h-auto p-1">
|
||||
{contentTabs.map((tab) => {
|
||||
const Icon = tab.icon;
|
||||
@@ -162,27 +228,22 @@ export function ContentManager({
|
||||
</TabsList>
|
||||
<Card>
|
||||
<CardContent className="p-6">
|
||||
{/* Profiler Tab */}
|
||||
<TabsContent value="profiler">
|
||||
<ProfilerTab onNavigate={onNavigate} user={user} />
|
||||
</TabsContent>
|
||||
|
||||
{/* Blogs Tab */}
|
||||
<TabsContent value="blogs">
|
||||
<BlogsTab onNavigate={onNavigate} user={user} />
|
||||
</TabsContent>
|
||||
|
||||
{/* FAQ Tab */}
|
||||
<TabsContent value="faq">
|
||||
<TabsContent value="faq"> {/* This matches the tab ID */}
|
||||
<FAQTab onNavigate={onNavigate} user={user} />
|
||||
</TabsContent>
|
||||
|
||||
{/* Webcasts Tab */}
|
||||
<TabsContent value="webcasts">
|
||||
<WebcastsTab onNavigate={onNavigate} user={user} />
|
||||
</TabsContent>
|
||||
|
||||
{/* Training Materials Tab */}
|
||||
<TabsContent value="training-materials">
|
||||
<TrainingMaterialsTab
|
||||
onNavigate={onNavigate}
|
||||
@@ -192,22 +253,18 @@ export function ContentManager({
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
{/* Reading Materials Tab */}
|
||||
<TabsContent value="reading-materials">
|
||||
<ReadingMaterialsTab onNavigate={onNavigate} user={user} />
|
||||
</TabsContent>
|
||||
|
||||
{/* Podcasts Tab */}
|
||||
<TabsContent value="podcasts">
|
||||
<PodcastsTab onNavigate={onNavigate} user={user} />
|
||||
</TabsContent>
|
||||
|
||||
{/* Case Studies Tab */}
|
||||
<TabsContent value="case-studies">
|
||||
<CaseStudiesTab onNavigate={onNavigate} user={user} />
|
||||
</TabsContent>
|
||||
|
||||
{/* KLC Content Archive Tab */}
|
||||
<TabsContent value="klc-content-archive">
|
||||
<KLCContentArchiveTab
|
||||
onNavigate={onNavigate}
|
||||
@@ -216,7 +273,6 @@ export function ContentManager({
|
||||
setActiveInnerTab={setActiveInnerTab}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Tabs>
|
||||
|
||||
@@ -214,7 +214,7 @@ export function EditBlog({
|
||||
}
|
||||
|
||||
toast.success(`Blog ${status === 'draft' ? 'updated' : 'published'} successfully`);
|
||||
onNavigate('/content');
|
||||
onNavigate('/content/blogs');
|
||||
} catch (error: any) {
|
||||
console.error('Error updating blog:', error);
|
||||
toast.error(error.data?.message || 'Failed to update blog. Please try again.');
|
||||
|
||||
@@ -134,7 +134,7 @@ export function EditCaseStudy({
|
||||
}
|
||||
|
||||
toast.success('Case study updated successfully');
|
||||
onNavigate('/content');
|
||||
onNavigate('/content/case-studies');
|
||||
} catch (error: any) {
|
||||
console.error('Error updating case study:', error);
|
||||
toast.error(error.data?.message || 'Failed to update case study. Please try again.');
|
||||
|
||||
@@ -157,7 +157,7 @@ export function EditFAQ({
|
||||
}
|
||||
|
||||
toast.success('FAQ updated successfully');
|
||||
onNavigate('/content');
|
||||
onNavigate('/content/faqs');
|
||||
} catch (error: any) {
|
||||
console.error('Error updating FAQ:', error);
|
||||
toast.error(error.data?.message || 'Failed to update FAQ. Please try again.');
|
||||
|
||||
@@ -145,7 +145,7 @@ export function EditKlcArchiveContent({
|
||||
}
|
||||
|
||||
toast.success('Archive content updated successfully');
|
||||
onNavigate('/content');
|
||||
onNavigate('/content/klc-content-archive');
|
||||
} catch (error: any) {
|
||||
console.error('Error updating archive content:', error);
|
||||
toast.error(error.data?.message || 'Failed to update archive content. Please try again.');
|
||||
|
||||
@@ -134,7 +134,7 @@ export function EditPodcast({
|
||||
}
|
||||
|
||||
toast.success('Podcast updated successfully');
|
||||
onNavigate('/content');
|
||||
onNavigate('/content/podcasts');
|
||||
} catch (error: any) {
|
||||
console.error('Error updating podcast:', error);
|
||||
toast.error(error.data?.message || 'Failed to update podcast. Please try again.');
|
||||
|
||||
@@ -136,7 +136,7 @@ export function EditReadingMaterial({
|
||||
}
|
||||
|
||||
toast.success('Reading material updated successfully');
|
||||
onNavigate('/content');
|
||||
onNavigate('/content/reading-materials');
|
||||
} catch (error: any) {
|
||||
console.error('Error updating reading material:', error);
|
||||
toast.error(error.data?.message || 'Failed to update reading material. Please try again.');
|
||||
|
||||
@@ -142,7 +142,7 @@ export function EditTrainingMaterial({
|
||||
}
|
||||
|
||||
toast.success('Training Material updated successfully');
|
||||
onNavigate('/content');
|
||||
onNavigate('/content/training-materials');
|
||||
} catch (error: any) {
|
||||
console.error('Error updating training material:', error);
|
||||
toast.error(error.data?.message || 'Failed to update training material. Please try again.');
|
||||
|
||||
@@ -140,7 +140,7 @@ export function EditWebcast({
|
||||
}
|
||||
|
||||
toast.success('Webcast updated successfully');
|
||||
onNavigate('/content');
|
||||
onNavigate('/content/webcasts');
|
||||
} catch (error: any) {
|
||||
console.error('Error updating webcast:', error);
|
||||
toast.error(error.data?.message || 'Failed to update webcast. Please try again.');
|
||||
|
||||
@@ -150,7 +150,7 @@ export function NewBlog({
|
||||
}
|
||||
|
||||
toast.success(`Blog ${status === 'draft' ? 'saved as draft' : 'published'} successfully`);
|
||||
onNavigate('/content');
|
||||
onNavigate('/content/blogs');
|
||||
} catch (error: any) {
|
||||
console.error('Error creating blog:', error);
|
||||
|
||||
@@ -179,7 +179,7 @@ export function NewBlog({
|
||||
<div className="flex items-center gap-4">
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => onNavigate('/content')}
|
||||
onClick={() => onNavigate('/content/blogs')}
|
||||
className="min-h-[44px] focus-visible:ring-2 focus-visible:ring-[var(--color-brand-primary)] focus-visible:ring-opacity-50"
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
|
||||
@@ -188,7 +188,7 @@ export function NewFAQ({
|
||||
}
|
||||
|
||||
toast.success(`${faqs.length} FAQ(s) created successfully`);
|
||||
onNavigate('/content');
|
||||
onNavigate('/content/faqs');
|
||||
} catch (error: any) {
|
||||
console.error('Error creating FAQs:', error);
|
||||
|
||||
@@ -242,7 +242,7 @@ export function NewFAQ({
|
||||
}
|
||||
|
||||
toast.success(`${faqs.length} FAQ(s) created successfully`);
|
||||
onNavigate('/content');
|
||||
onNavigate('/content/faqs');
|
||||
} catch (error: any) {
|
||||
console.error('Error creating FAQs:', error);
|
||||
toast.error(error.data?.message || 'Failed to save FAQs. Please try again.');
|
||||
|
||||
@@ -136,7 +136,7 @@ export function CaseStudiesTab({ onNavigate, user }: CaseStudiesTabProps) {
|
||||
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<span>
|
||||
Showing {enhancedCaseStudies.length} of {paginationMeta?.total || 0} items
|
||||
{/* Showing {enhancedCaseStudies.length} of {paginationMeta?.total || 0} items */}
|
||||
{paginationMeta && paginationMeta.totalPages > 1 && (
|
||||
<span> (Page {currentPage} of {paginationMeta.totalPages})</span>
|
||||
)}
|
||||
|
||||
@@ -112,7 +112,6 @@ export function KLCContentArchiveTab({
|
||||
setSelectedItems([]);
|
||||
};
|
||||
|
||||
// REMOVED: Filter by category since API data doesn't have category field
|
||||
// Use all data instead of filtering by category
|
||||
const filteredArchive = archiveContent.filter((archive: any) =>
|
||||
archive.title?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
@@ -192,7 +191,7 @@ export function KLCContentArchiveTab({
|
||||
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<span>
|
||||
Showing {enhancedArchive.length} of {paginationMeta?.total || 0} items
|
||||
{/* Showing {enhancedArchive.length} of {paginationMeta?.total || 0} items */}
|
||||
{paginationMeta && paginationMeta.totalPages > 1 && (
|
||||
<span> (Page {currentPage} of {paginationMeta.totalPages})</span>
|
||||
)}
|
||||
|
||||
@@ -136,7 +136,7 @@ export function PodcastsTab({ onNavigate, user }: PodcastsTabProps) {
|
||||
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<span>
|
||||
Showing {enhancedPodcasts.length} of {paginationMeta?.total || 0} items
|
||||
{/* Showing {enhancedPodcasts.length} of {paginationMeta?.total || 0} items */}
|
||||
{paginationMeta && paginationMeta.totalPages > 1 && (
|
||||
<span> (Page {currentPage} of {paginationMeta.totalPages})</span>
|
||||
)}
|
||||
|
||||
@@ -133,7 +133,7 @@ export function ReadingMaterialsTab({ onNavigate, user }: ReadingMaterialsTabPro
|
||||
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<span>
|
||||
Showing {enhancedReadingMaterials.length} of {paginationMeta?.total || 0} items
|
||||
{/* Showing {enhancedReadingMaterials.length} of {paginationMeta?.total || 0} items */}
|
||||
{paginationMeta && paginationMeta.totalPages > 1 && (
|
||||
<span> (Page {currentPage} of {paginationMeta.totalPages})</span>
|
||||
)}
|
||||
|
||||
@@ -211,7 +211,7 @@ export function TrainingMaterialsTab({
|
||||
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<span>
|
||||
Showing {enhancedMaterials.length} of {paginationMeta?.total || 0} items
|
||||
{/* Showing {enhancedMaterials.length} of {paginationMeta?.total || 0} items */}
|
||||
{paginationMeta && paginationMeta.totalPages > 1 && (
|
||||
<span> (Page {currentPage} of {paginationMeta.totalPages})</span>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user