Forum Tenant sistemi hatası düzeltildi.

This commit is contained in:
Sedat ÖZTÜRK 2025-06-24 17:24:08 +03:00
parent 10493bd067
commit 4f2612ab03
11 changed files with 151 additions and 105 deletions

View file

@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
"revision": "3ca0b8505b4bec776b69afdba2768812" "revision": "3ca0b8505b4bec776b69afdba2768812"
}, { }, {
"url": "index.html", "url": "index.html",
"revision": "0.3kkdvt11rc8" "revision": "0.edm7dfkr7s"
}], {}); }], {});
workbox.cleanupOutdatedCaches(); workbox.cleanupOutdatedCaches();
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {

View file

@ -5,7 +5,7 @@ import { useForumData } from './useForumData'
import { ForumView } from './forum/ForumView' import { ForumView } from './forum/ForumView'
export function Forum() { export function Forum() {
const { user, tenantId } = useStoreState((state) => state.auth) const { user, tenant } = useStoreState((state) => state.auth)
const { const {
categories, categories,
topics, topics,

View file

@ -5,7 +5,6 @@ import { useForumData } from './useForumData'
import { AdminView } from './admin/AdminView' import { AdminView } from './admin/AdminView'
export function Management() { export function Management() {
const { user, tenantId } = useStoreState((state) => state.auth)
const { const {
categories, categories,
topics, topics,
@ -34,12 +33,6 @@ export function Management() {
clearError, clearError,
} = useForumData() } = useForumData()
const [selectedCategory, setSelectedCategory] = useState<ForumCategory | null>(null)
const [selectedTopic, setSelectedTopic] = useState<ForumTopic | null>(null)
const [forumViewState, setForumViewState] = useState<'categories' | 'topics' | 'posts'>(
'categories',
)
useEffect(() => { useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => { const handleKeyDown = (e: KeyboardEvent) => {
if ((e.metaKey || e.ctrlKey) && e.key === 'k') { if ((e.metaKey || e.ctrlKey) && e.key === 'k') {

View file

@ -1,36 +1,39 @@
import React, { useState } from 'react'; import React, { useState } from 'react'
import { Plus, Edit2, Trash2, Lock, Unlock, Eye, EyeOff, Loader2 } from 'lucide-react'; import { Plus, Edit2, Trash2, Lock, Unlock, Eye, EyeOff, Loader2 } from 'lucide-react'
import { ForumCategory } from '@/proxy/forum/forum'; import { ForumCategory } from '@/proxy/forum/forum'
import { useStoreState } from '@/store/store'
interface CategoryManagementProps { interface CategoryManagementProps {
categories: ForumCategory[]; categories: ForumCategory[]
loading: boolean; loading: boolean
onCreateCategory: (category: { onCreateCategory: (category: {
name: string; name: string
slug: string; slug: string
description: string; description: string
icon: string; icon: string
displayOrder: number; displayOrder: number
isActive: boolean; isActive: boolean
isLocked: boolean; isLocked: boolean
}) => Promise<void>; tenantId?: string
onUpdateCategory: (id: string, category: Partial<ForumCategory>) => Promise<void>; }) => Promise<void>
onDeleteCategory: (id: string) => Promise<void>; onUpdateCategory: (id: string, category: Partial<ForumCategory>) => Promise<void>
onUpdateCategoryLockState: (id: string) => Promise<void>; onDeleteCategory: (id: string) => Promise<void>
onUpdateCategoryActiveState: (id: string) => Promise<void>; onUpdateCategoryLockState: (id: string) => Promise<void>
onUpdateCategoryActiveState: (id: string) => Promise<void>
} }
export function CategoryManagement({ export function CategoryManagement({
categories, categories,
loading, loading,
onCreateCategory, onCreateCategory,
onUpdateCategory, onUpdateCategory,
onDeleteCategory, onDeleteCategory,
onUpdateCategoryLockState, onUpdateCategoryLockState,
onUpdateCategoryActiveState onUpdateCategoryActiveState,
}: CategoryManagementProps) { }: CategoryManagementProps) {
const [showCreateForm, setShowCreateForm] = useState(false); const { tenant } = useStoreState((state) => state.auth)
const [editingCategory, setEditingCategory] = useState<ForumCategory | null>(null); const [showCreateForm, setShowCreateForm] = useState(false)
const [editingCategory, setEditingCategory] = useState<ForumCategory | null>(null)
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
name: '', name: '',
slug: '', slug: '',
@ -39,8 +42,9 @@ export function CategoryManagement({
displayOrder: 0, displayOrder: 0,
isActive: true, isActive: true,
isLocked: false, isLocked: false,
}); tenantId: ''
const [submitting, setSubmitting] = useState(false); })
const [submitting, setSubmitting] = useState(false)
const resetForm = () => { const resetForm = () => {
setFormData({ setFormData({
@ -51,32 +55,33 @@ export function CategoryManagement({
displayOrder: 0, displayOrder: 0,
isActive: true, isActive: true,
isLocked: false, isLocked: false,
}); tenantId: ''
setShowCreateForm(false); })
setEditingCategory(null); setShowCreateForm(false)
}; setEditingCategory(null)
}
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
if (submitting) return; if (submitting) return
try { try {
setSubmitting(true); setSubmitting(true)
if (editingCategory) { if (editingCategory) {
await onUpdateCategory(editingCategory.id, formData); await onUpdateCategory(editingCategory.id, formData)
} else { } else {
await onCreateCategory(formData); await onCreateCategory(formData)
} }
resetForm(); resetForm()
} catch (error) { } catch (error) {
console.error('Error submitting form:', error); console.error('Error submitting form:', error)
} finally { } finally {
setSubmitting(false); setSubmitting(false)
} }
}; }
const handleEdit = (category: ForumCategory) => { const handleEdit = (category: ForumCategory) => {
setEditingCategory(category); setEditingCategory(category)
setFormData({ setFormData({
name: category.name, name: category.name,
slug: category.slug, slug: category.slug,
@ -85,35 +90,40 @@ export function CategoryManagement({
displayOrder: category.displayOrder, displayOrder: category.displayOrder,
isActive: category.isActive, isActive: category.isActive,
isLocked: category.isLocked, isLocked: category.isLocked,
}); tenantId: tenant.tenantId ?? ''
setShowCreateForm(true); })
}; setShowCreateForm(true)
}
const handleToggleActive = async (category: ForumCategory) => { const handleToggleActive = async (category: ForumCategory) => {
try { try {
await onUpdateCategoryActiveState(category.id); await onUpdateCategoryActiveState(category.id)
} catch (error) { } catch (error) {
console.error('Error toggling category status:', error); console.error('Error toggling category status:', error)
} }
}; }
const handleToggleLocked = async (category: ForumCategory) => { const handleToggleLocked = async (category: ForumCategory) => {
try { try {
await onUpdateCategoryLockState(category.id); await onUpdateCategoryLockState(category.id)
} catch (error) { } catch (error) {
console.error('Error toggling category lock:', error); console.error('Error toggling category lock:', error)
} }
}; }
const handleDelete = async (id: string) => { const handleDelete = async (id: string) => {
if (confirm('Are you sure you want to delete this category? This will also delete all topics and posts in this category.')) { if (
confirm(
'Are you sure you want to delete this category? This will also delete all topics and posts in this category.',
)
) {
try { try {
await onDeleteCategory(id); await onDeleteCategory(id)
} catch (error) { } catch (error) {
console.error('Error deleting category:', error); console.error('Error deleting category:', error)
} }
} }
}; }
return ( return (
<div className="space-y-6"> <div className="space-y-6">
@ -158,7 +168,7 @@ export function CategoryManagement({
/> />
</div> </div>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1">Description</label> <label className="block text-sm font-medium text-gray-700 mb-1">Description</label>
<textarea <textarea
@ -169,7 +179,7 @@ export function CategoryManagement({
required required
/> />
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1">Icon (Emoji)</label> <label className="block text-sm font-medium text-gray-700 mb-1">Icon (Emoji)</label>
@ -182,11 +192,15 @@ export function CategoryManagement({
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1">Display Order</label> <label className="block text-sm font-medium text-gray-700 mb-1">
Display Order
</label>
<input <input
type="number" type="number"
value={formData.displayOrder} value={formData.displayOrder}
onChange={(e) => setFormData({ ...formData, displayOrder: parseInt(e.target.value) })} onChange={(e) =>
setFormData({ ...formData, displayOrder: parseInt(e.target.value) })
}
className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/> />
</div> </div>
@ -211,7 +225,7 @@ export function CategoryManagement({
</label> </label>
</div> </div>
</div> </div>
<div className="flex justify-end space-x-3"> <div className="flex justify-end space-x-3">
<button <button
type="button" type="button"
@ -239,7 +253,7 @@ export function CategoryManagement({
<div className="px-6 py-4 border-b border-gray-200"> <div className="px-6 py-4 border-b border-gray-200">
<h3 className="text-lg font-semibold text-gray-900">Categories ({categories.length})</h3> <h3 className="text-lg font-semibold text-gray-900">Categories ({categories.length})</h3>
</div> </div>
{loading ? ( {loading ? (
<div className="p-8 text-center"> <div className="p-8 text-center">
<Loader2 className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" /> <Loader2 className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
@ -258,10 +272,14 @@ export function CategoryManagement({
<div className="flex items-center space-x-2 mb-1"> <div className="flex items-center space-x-2 mb-1">
<h4 className="text-lg font-semibold text-gray-900">{category.name}</h4> <h4 className="text-lg font-semibold text-gray-900">{category.name}</h4>
{!category.isActive && ( {!category.isActive && (
<span className="px-2 py-1 bg-red-100 text-red-700 text-xs rounded-full">Inactive</span> <span className="px-2 py-1 bg-red-100 text-red-700 text-xs rounded-full">
Inactive
</span>
)} )}
{category.isLocked && ( {category.isLocked && (
<span className="px-2 py-1 bg-yellow-100 text-yellow-700 text-xs rounded-full">Locked</span> <span className="px-2 py-1 bg-yellow-100 text-yellow-700 text-xs rounded-full">
Locked
</span>
)} )}
</div> </div>
<p className="text-gray-600 mb-2">{category.description}</p> <p className="text-gray-600 mb-2">{category.description}</p>
@ -272,7 +290,7 @@ export function CategoryManagement({
</div> </div>
</div> </div>
</div> </div>
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<button <button
onClick={() => handleToggleActive(category)} onClick={() => handleToggleActive(category)}
@ -283,9 +301,13 @@ export function CategoryManagement({
}`} }`}
title={category.isActive ? 'Hide Category' : 'Show Category'} title={category.isActive ? 'Hide Category' : 'Show Category'}
> >
{category.isActive ? <Eye className="w-4 h-4" /> : <EyeOff className="w-4 h-4" />} {category.isActive ? (
<Eye className="w-4 h-4" />
) : (
<EyeOff className="w-4 h-4" />
)}
</button> </button>
<button <button
onClick={() => handleToggleLocked(category)} onClick={() => handleToggleLocked(category)}
className={`p-2 rounded-lg transition-colors ${ className={`p-2 rounded-lg transition-colors ${
@ -295,9 +317,13 @@ export function CategoryManagement({
}`} }`}
title={category.isLocked ? 'Unlock Category' : 'Lock Category'} title={category.isLocked ? 'Unlock Category' : 'Lock Category'}
> >
{category.isLocked ? <Lock className="w-4 h-4" /> : <Unlock className="w-4 h-4" />} {category.isLocked ? (
<Lock className="w-4 h-4" />
) : (
<Unlock className="w-4 h-4" />
)}
</button> </button>
<button <button
onClick={() => handleEdit(category)} onClick={() => handleEdit(category)}
className="p-2 text-blue-600 hover:bg-blue-100 rounded-lg transition-colors" className="p-2 text-blue-600 hover:bg-blue-100 rounded-lg transition-colors"
@ -305,7 +331,7 @@ export function CategoryManagement({
> >
<Edit2 className="w-4 h-4" /> <Edit2 className="w-4 h-4" />
</button> </button>
<button <button
onClick={() => handleDelete(category.id)} onClick={() => handleDelete(category.id)}
className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors" className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors"
@ -321,5 +347,5 @@ export function CategoryManagement({
)} )}
</div> </div>
</div> </div>
); )
} }

View file

@ -3,12 +3,18 @@ import { Plus, Edit2, Trash2, CheckCircle, Circle, Heart, Loader2 } from 'lucide
import { ForumPost, ForumTopic } from '@/proxy/forum/forum' import { ForumPost, ForumTopic } from '@/proxy/forum/forum'
import ReactQuill from 'react-quill' import ReactQuill from 'react-quill'
import 'react-quill/dist/quill.snow.css' import 'react-quill/dist/quill.snow.css'
import { useStoreState } from '@/store/store'
interface PostManagementProps { interface PostManagementProps {
posts: ForumPost[] posts: ForumPost[]
topics: ForumTopic[] topics: ForumTopic[]
loading: boolean loading: boolean
onCreatePost: (post: { topicId: string; content: string; parentPostId?: string }) => Promise<void> onCreatePost: (post: {
topicId: string
content: string
parentPostId?: string
tenantId?: string
}) => Promise<void>
onUpdatePost: (id: string, post: Partial<ForumPost>) => Promise<void> onUpdatePost: (id: string, post: Partial<ForumPost>) => Promise<void>
onDeletePost: (id: string) => Promise<void> onDeletePost: (id: string) => Promise<void>
onMarkPostAsAcceptedAnswer: (id: string) => Promise<void> onMarkPostAsAcceptedAnswer: (id: string) => Promise<void>
@ -25,11 +31,14 @@ export function PostManagement({
onMarkPostAsAcceptedAnswer, onMarkPostAsAcceptedAnswer,
onUnmarkPostAsAcceptedAnswer, onUnmarkPostAsAcceptedAnswer,
}: PostManagementProps) { }: PostManagementProps) {
const { tenant } = useStoreState((state) => state.auth)
const [content, setContent] = useState('') const [content, setContent] = useState('')
const [showCreateForm, setShowCreateForm] = useState(false) const [showCreateForm, setShowCreateForm] = useState(false)
const [editingPost, setEditingPost] = useState<ForumPost | null>(null) const [editingPost, setEditingPost] = useState<ForumPost | null>(null)
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
topicId: '', topicId: '',
parentPostId: '',
tenantId: '',
isAcceptedAnswer: false, isAcceptedAnswer: false,
}) })
const [submitting, setSubmitting] = useState(false) const [submitting, setSubmitting] = useState(false)
@ -37,6 +46,8 @@ export function PostManagement({
const resetForm = () => { const resetForm = () => {
setFormData({ setFormData({
topicId: '', topicId: '',
parentPostId: '',
tenantId: '',
isAcceptedAnswer: false, isAcceptedAnswer: false,
}) })
setShowCreateForm(false) setShowCreateForm(false)
@ -69,6 +80,8 @@ export function PostManagement({
setEditingPost(post) setEditingPost(post)
setFormData({ setFormData({
topicId: post.topicId, topicId: post.topicId,
parentPostId: '',
tenantId: tenant.tenantId ?? '',
isAcceptedAnswer: post.isAcceptedAnswer, isAcceptedAnswer: post.isAcceptedAnswer,
}) })
setContent(post.content) setContent(post.content)

View file

@ -13,6 +13,7 @@ import {
Loader2, Loader2,
} from 'lucide-react' } from 'lucide-react'
import { ForumCategory, ForumTopic } from '@/proxy/forum/forum' import { ForumCategory, ForumTopic } from '@/proxy/forum/forum'
import { useStoreState } from '@/store/store'
interface TopicManagementProps { interface TopicManagementProps {
topics: ForumTopic[] topics: ForumTopic[]
@ -24,6 +25,7 @@ interface TopicManagementProps {
categoryId: string categoryId: string
isPinned?: boolean isPinned?: boolean
isLocked?: boolean isLocked?: boolean
tenantId?: string
}) => Promise<void> }) => Promise<void>
onUpdateTopic: (id: string, topic: Partial<ForumTopic>) => Promise<void> onUpdateTopic: (id: string, topic: Partial<ForumTopic>) => Promise<void>
onDeleteTopic: (id: string) => Promise<void> onDeleteTopic: (id: string) => Promise<void>
@ -49,6 +51,7 @@ export function TopicManagement({
onMarkTopicAsSolved, onMarkTopicAsSolved,
onMarkTopicAsUnsolved, onMarkTopicAsUnsolved,
}: TopicManagementProps) { }: TopicManagementProps) {
const { tenant } = useStoreState((state) => state.auth)
const [showCreateForm, setShowCreateForm] = useState(false) const [showCreateForm, setShowCreateForm] = useState(false)
const [editingTopic, setEditingTopic] = useState<ForumTopic | null>(null) const [editingTopic, setEditingTopic] = useState<ForumTopic | null>(null)
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@ -58,6 +61,7 @@ export function TopicManagement({
isPinned: false, isPinned: false,
isLocked: false, isLocked: false,
isSolved: false, isSolved: false,
tenantId: '',
}) })
const [submitting, setSubmitting] = useState(false) const [submitting, setSubmitting] = useState(false)
@ -69,6 +73,7 @@ export function TopicManagement({
isPinned: false, isPinned: false,
isLocked: false, isLocked: false,
isSolved: false, isSolved: false,
tenantId: '',
}) })
setShowCreateForm(false) setShowCreateForm(false)
setEditingTopic(null) setEditingTopic(null)
@ -102,6 +107,7 @@ export function TopicManagement({
isPinned: topic.isPinned, isPinned: topic.isPinned,
isLocked: topic.isLocked, isLocked: topic.isLocked,
isSolved: topic.isSolved, isSolved: topic.isSolved,
tenantId: tenant.tenantId ?? ''
}) })
setShowCreateForm(true) setShowCreateForm(true)
} }

View file

@ -2,21 +2,23 @@ import React, { useState } from 'react';
import { X } from 'lucide-react'; import { X } from 'lucide-react';
import ReactQuill from 'react-quill'; import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css'; import 'react-quill/dist/quill.snow.css';
import { useStoreState } from '@/store/store';
interface CreatePostModalProps { interface CreatePostModalProps {
onClose: () => void; onClose: () => void;
onSubmit: (data: { content: string }) => void; onSubmit: (data: { content: string, parentPostId?: string, tenantId?: string }) => void;
parentPostId?: string; parentPostId: string
} }
export function CreatePostModal({ onClose, onSubmit, parentPostId }: CreatePostModalProps) { export function CreatePostModal({ onClose, onSubmit, parentPostId }: CreatePostModalProps) {
const [content, setContent] = useState(''); const [content, setContent] = useState('');
const { tenant } = useStoreState((state) => state.auth)
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
const plainText = content.replace(/<[^>]+>/g, '').trim(); // HTML etiketlerini temizle const plainText = content.replace(/<[^>]+>/g, '').trim(); // HTML etiketlerini temizle
if (plainText) { if (plainText) {
onSubmit({ content }); onSubmit({ content, parentPostId, tenantId: tenant.tenantId });
} }
}; };

View file

@ -1,19 +1,21 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { X } from 'lucide-react'; import { X } from 'lucide-react';
import { useStoreState } from '@/store/store';
interface CreateTopicModalProps { interface CreateTopicModalProps {
onClose: () => void; onClose: () => void;
onSubmit: (data: { title: string; content: string }) => void; onSubmit: (data: { title: string; content: string, tenantId?: string }) => void;
} }
export function CreateTopicModal({ onClose, onSubmit }: CreateTopicModalProps) { export function CreateTopicModal({ onClose, onSubmit }: CreateTopicModalProps) {
const [title, setTitle] = useState(''); const [title, setTitle] = useState('');
const [content, setContent] = useState(''); const [content, setContent] = useState('');
const { tenant } = useStoreState((state) => state.auth)
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
if (title.trim() && content.trim()) { if (title.trim() && content.trim()) {
onSubmit({ title: title.trim(), content: content.trim() }); onSubmit({ title: title.trim(), content: content.trim(), tenantId: tenant.tenantId });
} }
}; };

View file

@ -18,10 +18,6 @@ export function ForumPostCard({
isFirst = false, isFirst = false,
isLiked = false, isLiked = false,
}: PostCardProps) { }: PostCardProps) {
const handleLike = () => {
onLike(post.id, isFirst)
}
const formatDate = (value: string | Date) => { const formatDate = (value: string | Date) => {
const date = value instanceof Date ? value : new Date(value) const date = value instanceof Date ? value : new Date(value)
if (isNaN(date.getTime())) return 'Invalid Date' if (isNaN(date.getTime())) return 'Invalid Date'
@ -67,7 +63,10 @@ export function ForumPostCard({
</div> </div>
<div className="prose prose-sm max-w-none mb-4"> <div className="prose prose-sm max-w-none mb-4">
<p className="text-gray-700 whitespace-pre-wrap" dangerouslySetInnerHTML={{ __html: post.content }} /> <p
className="text-gray-700 whitespace-pre-wrap"
dangerouslySetInnerHTML={{ __html: post.content }}
/>
</div> </div>
<div className="flex items-center space-x-4"> <div className="flex items-center space-x-4">
@ -83,13 +82,13 @@ export function ForumPostCard({
<span>{post.likeCount}</span> <span>{post.likeCount}</span>
</button> </button>
<button {!isFirst && (<button
onClick={() => onReply(post.id)} onClick={() => onReply(post.id)}
className="flex items-center space-x-1 px-3 py-1 rounded-full text-sm bg-gray-100 text-gray-600 hover:bg-gray-200 transition-colors" className="flex items-center space-x-1 px-3 py-1 rounded-full text-sm bg-gray-100 text-gray-600 hover:bg-gray-200 transition-colors"
> >
<Reply className="w-4 h-4" /> <Reply className="w-4 h-4" />
<span>Reply</span> <span>Reply</span>
</button> </button>)}
</div> </div>
</div> </div>
</div> </div>

View file

@ -9,6 +9,7 @@ import { buildPostTree } from './utils'
import { ForumPostCard } from './ForumPostCard' import { ForumPostCard } from './ForumPostCard'
import { ForumCategoryCard } from './ForumCategoryCard' import { ForumCategoryCard } from './ForumCategoryCard'
import { ForumTopicCard } from './ForumTopicCard' import { ForumTopicCard } from './ForumTopicCard'
import { useStoreState } from '@/store/store'
interface ForumViewProps { interface ForumViewProps {
categories: ForumCategory[] categories: ForumCategory[]
@ -21,8 +22,14 @@ interface ForumViewProps {
categoryId: string categoryId: string
isPinned?: boolean isPinned?: boolean
isLocked?: boolean isLocked?: boolean
tenantId?: string
}) => Promise<void>
onCreatePost: (post: {
topicId: string
content: string
parentPostId?: string
tenantId?: string
}) => Promise<void> }) => Promise<void>
onCreatePost: (post: { topicId: string; content: string; parentPostId?: string }) => Promise<void>
onLikePost: (id: string) => Promise<void> onLikePost: (id: string) => Promise<void>
onUnlikePost: (id: string) => Promise<void> onUnlikePost: (id: string) => Promise<void>
currentUserId: string currentUserId: string
@ -68,6 +75,7 @@ export function ForumView({
const [isSearchModalOpen, setIsSearchModalOpen] = useState(false) const [isSearchModalOpen, setIsSearchModalOpen] = useState(false)
const [postLikeCounts, setPostLikeCounts] = useState<Record<string, number>>({}) const [postLikeCounts, setPostLikeCounts] = useState<Record<string, number>>({})
const { tenant } = useStoreState((state) => state.auth)
const handleSearchCategorySelect = (category: ForumCategory) => { const handleSearchCategorySelect = (category: ForumCategory) => {
if (onCategorySelect) onCategorySelect(category) if (onCategorySelect) onCategorySelect(category)
@ -201,6 +209,7 @@ export function ForumView({
categoryId: selectedCategory.id, categoryId: selectedCategory.id,
isPinned: false, isPinned: false,
isLocked: false, isLocked: false,
tenantId: tenant.tenantId,
}) })
setShowCreateTopic(false) setShowCreateTopic(false)
} catch (error) { } catch (error) {
@ -215,10 +224,11 @@ export function ForumView({
await onCreatePost({ await onCreatePost({
topicId: selectedTopic.id, topicId: selectedTopic.id,
content: postData.content, content: postData.content,
parentPostId: replyToPostId, // buraya dikkat parentPostId: replyToPostId,
tenantId: tenant.tenantId,
}) })
setShowCreatePost(false) setShowCreatePost(false)
setReplyToPostId(undefined) // temizle setReplyToPostId(undefined)
} catch (error) { } catch (error) {
console.error('Error creating post:', error) console.error('Error creating post:', error)
} }
@ -271,13 +281,6 @@ export function ForumView({
} }
} }
// 🧠 Helper function to read initial like count
const getInitialLikeCount = (postId: string) => {
if (selectedTopic?.id === postId) return selectedTopic.likeCount
const post = posts.find((p) => p.id === postId)
return post?.likeCount ?? 0
}
const handleReply = (postId: string) => { const handleReply = (postId: string) => {
setReplyToPostId(postId) setReplyToPostId(postId)
setShowCreatePost(true) setShowCreatePost(true)
@ -446,9 +449,10 @@ export function ForumView({
authorId: selectedTopic.authorId, authorId: selectedTopic.authorId,
authorName: selectedTopic.authorName, authorName: selectedTopic.authorName,
likeCount: postLikeCounts[selectedTopic.id] ?? selectedTopic.likeCount, likeCount: postLikeCounts[selectedTopic.id] ?? selectedTopic.likeCount,
isAcceptedAnswer: false, isAcceptedAnswer: false,
parentPostId: undefined, parentPostId: undefined,
creationTime: selectedTopic.creationTime, creationTime: selectedTopic.creationTime,
tenantId: selectedTopic.tenantId
}} }}
onLike={handleLike} onLike={handleLike}
onReply={handleReply} onReply={handleReply}

View file

@ -248,9 +248,10 @@ export function SearchModal({
<div className="font-medium text-gray-900 text-sm line-clamp-1"> <div className="font-medium text-gray-900 text-sm line-clamp-1">
{getTopicTitle(post.topicId)} {getTopicTitle(post.topicId)}
</div> </div>
<div className="text-sm text-gray-600 line-clamp-2 mt-1"> <div
{post.content} className="text-sm text-gray-600 line-clamp-2 mt-1"
</div> dangerouslySetInnerHTML={{ __html: post.content }}
></div>
<div className="text-xs text-gray-500 mt-1"> <div className="text-xs text-gray-500 mt-1">
by {post.authorName} {formatDate(post.creationTime)} by {post.authorName} {formatDate(post.creationTime)}
</div> </div>