140 lines
4.6 KiB
TypeScript
140 lines
4.6 KiB
TypeScript
"use client";
|
|
import { useEffect, useState } from 'react';
|
|
import { useKnowledgeBaseArticle } from '@/lib/hooks/useSupport';
|
|
import { markArticleHelpful } from '@/lib/api/supportService';
|
|
|
|
interface KnowledgeBaseArticleModalProps {
|
|
slug: string;
|
|
onClose: () => void;
|
|
}
|
|
|
|
const KnowledgeBaseArticleModal = ({ slug, onClose }: KnowledgeBaseArticleModalProps) => {
|
|
const { article, loading, error } = useKnowledgeBaseArticle(slug);
|
|
const [feedbackGiven, setFeedbackGiven] = useState(false);
|
|
|
|
useEffect(() => {
|
|
// Prevent body scroll when modal is open
|
|
document.body.style.overflow = 'hidden';
|
|
|
|
return () => {
|
|
document.body.style.overflow = 'unset';
|
|
};
|
|
}, []);
|
|
|
|
const handleFeedback = async (helpful: boolean) => {
|
|
if (!article || feedbackGiven) return;
|
|
|
|
try {
|
|
await markArticleHelpful(slug, helpful);
|
|
setFeedbackGiven(true);
|
|
} catch (error) {
|
|
console.error('Error submitting feedback:', error);
|
|
}
|
|
};
|
|
|
|
const formatDate = (dateString: string) => {
|
|
const date = new Date(dateString);
|
|
return date.toLocaleDateString('en-US', {
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric'
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className="kb-modal-overlay" onClick={onClose}>
|
|
<div className="kb-modal" onClick={(e) => e.stopPropagation()}>
|
|
<button className="modal-close" onClick={onClose} aria-label="Close modal">
|
|
<i className="fa-solid fa-times"></i>
|
|
</button>
|
|
|
|
<div className="modal-content">
|
|
{loading && (
|
|
<div className="loading-state">
|
|
<div className="spinner-border" role="status">
|
|
<span className="visually-hidden">Loading...</span>
|
|
</div>
|
|
<p>Loading article...</p>
|
|
</div>
|
|
)}
|
|
|
|
{error && (
|
|
<div className="error-state">
|
|
<i className="fa-solid fa-triangle-exclamation"></i>
|
|
<h3>Error Loading Article</h3>
|
|
<p>{error}</p>
|
|
</div>
|
|
)}
|
|
|
|
{article && (
|
|
<>
|
|
<div className="article-header">
|
|
{article.is_featured && (
|
|
<span className="featured-badge">
|
|
<i className="fa-solid fa-star me-1"></i>
|
|
Featured
|
|
</span>
|
|
)}
|
|
<h2>{article.title}</h2>
|
|
<div className="article-meta">
|
|
<span className="meta-item">
|
|
<i className="fa-solid fa-folder me-1"></i>
|
|
{article.category_name}
|
|
</span>
|
|
<span className="meta-item">
|
|
<i className="fa-solid fa-calendar me-1"></i>
|
|
{formatDate(article.published_at || article.created_at)}
|
|
</span>
|
|
<span className="meta-item">
|
|
<i className="fa-solid fa-eye me-1"></i>
|
|
{article.view_count} views
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="article-body">
|
|
<div
|
|
className="article-content"
|
|
dangerouslySetInnerHTML={{ __html: article.content || article.summary }}
|
|
/>
|
|
</div>
|
|
|
|
<div className="article-footer">
|
|
<div className="article-feedback">
|
|
<h4>Was this article helpful?</h4>
|
|
{feedbackGiven ? (
|
|
<p className="feedback-thanks">
|
|
<i className="fa-solid fa-check-circle me-2"></i>
|
|
Thank you for your feedback!
|
|
</p>
|
|
) : (
|
|
<div className="feedback-buttons">
|
|
<button
|
|
className="btn btn-outline-success"
|
|
onClick={() => handleFeedback(true)}
|
|
>
|
|
<i className="fa-solid fa-thumbs-up me-2"></i>
|
|
Yes ({article.helpful_count})
|
|
</button>
|
|
<button
|
|
className="btn btn-outline-danger"
|
|
onClick={() => handleFeedback(false)}
|
|
>
|
|
<i className="fa-solid fa-thumbs-down me-2"></i>
|
|
No ({article.not_helpful_count})
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default KnowledgeBaseArticleModal;
|
|
|