Forum Tenant sistemi hatası düzeltildi.
This commit is contained in:
parent
10493bd067
commit
4f2612ab03
11 changed files with 151 additions and 105 deletions
|
|
@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
|
|||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||
}, {
|
||||
"url": "index.html",
|
||||
"revision": "0.3kkdvt11rc8"
|
||||
"revision": "0.edm7dfkr7s"
|
||||
}], {});
|
||||
workbox.cleanupOutdatedCaches();
|
||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { useForumData } from './useForumData'
|
|||
import { ForumView } from './forum/ForumView'
|
||||
|
||||
export function Forum() {
|
||||
const { user, tenantId } = useStoreState((state) => state.auth)
|
||||
const { user, tenant } = useStoreState((state) => state.auth)
|
||||
const {
|
||||
categories,
|
||||
topics,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { useForumData } from './useForumData'
|
|||
import { AdminView } from './admin/AdminView'
|
||||
|
||||
export function Management() {
|
||||
const { user, tenantId } = useStoreState((state) => state.auth)
|
||||
const {
|
||||
categories,
|
||||
topics,
|
||||
|
|
@ -34,12 +33,6 @@ export function Management() {
|
|||
clearError,
|
||||
} = useForumData()
|
||||
|
||||
const [selectedCategory, setSelectedCategory] = useState<ForumCategory | null>(null)
|
||||
const [selectedTopic, setSelectedTopic] = useState<ForumTopic | null>(null)
|
||||
const [forumViewState, setForumViewState] = useState<'categories' | 'topics' | 'posts'>(
|
||||
'categories',
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
||||
|
|
|
|||
|
|
@ -1,36 +1,39 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Plus, Edit2, Trash2, Lock, Unlock, Eye, EyeOff, Loader2 } from 'lucide-react';
|
||||
import { ForumCategory } from '@/proxy/forum/forum';
|
||||
import React, { useState } from 'react'
|
||||
import { Plus, Edit2, Trash2, Lock, Unlock, Eye, EyeOff, Loader2 } from 'lucide-react'
|
||||
import { ForumCategory } from '@/proxy/forum/forum'
|
||||
import { useStoreState } from '@/store/store'
|
||||
|
||||
interface CategoryManagementProps {
|
||||
categories: ForumCategory[];
|
||||
loading: boolean;
|
||||
categories: ForumCategory[]
|
||||
loading: boolean
|
||||
onCreateCategory: (category: {
|
||||
name: string;
|
||||
slug: string;
|
||||
description: string;
|
||||
icon: string;
|
||||
displayOrder: number;
|
||||
isActive: boolean;
|
||||
isLocked: boolean;
|
||||
}) => Promise<void>;
|
||||
onUpdateCategory: (id: string, category: Partial<ForumCategory>) => Promise<void>;
|
||||
onDeleteCategory: (id: string) => Promise<void>;
|
||||
onUpdateCategoryLockState: (id: string) => Promise<void>;
|
||||
onUpdateCategoryActiveState: (id: string) => Promise<void>;
|
||||
name: string
|
||||
slug: string
|
||||
description: string
|
||||
icon: string
|
||||
displayOrder: number
|
||||
isActive: boolean
|
||||
isLocked: boolean
|
||||
tenantId?: string
|
||||
}) => Promise<void>
|
||||
onUpdateCategory: (id: string, category: Partial<ForumCategory>) => Promise<void>
|
||||
onDeleteCategory: (id: string) => Promise<void>
|
||||
onUpdateCategoryLockState: (id: string) => Promise<void>
|
||||
onUpdateCategoryActiveState: (id: string) => Promise<void>
|
||||
}
|
||||
|
||||
export function CategoryManagement({
|
||||
categories,
|
||||
export function CategoryManagement({
|
||||
categories,
|
||||
loading,
|
||||
onCreateCategory,
|
||||
onUpdateCategory,
|
||||
onCreateCategory,
|
||||
onUpdateCategory,
|
||||
onDeleteCategory,
|
||||
onUpdateCategoryLockState,
|
||||
onUpdateCategoryActiveState
|
||||
onUpdateCategoryActiveState,
|
||||
}: CategoryManagementProps) {
|
||||
const [showCreateForm, setShowCreateForm] = useState(false);
|
||||
const [editingCategory, setEditingCategory] = useState<ForumCategory | null>(null);
|
||||
const { tenant } = useStoreState((state) => state.auth)
|
||||
const [showCreateForm, setShowCreateForm] = useState(false)
|
||||
const [editingCategory, setEditingCategory] = useState<ForumCategory | null>(null)
|
||||
const [formData, setFormData] = useState({
|
||||
name: '',
|
||||
slug: '',
|
||||
|
|
@ -39,8 +42,9 @@ export function CategoryManagement({
|
|||
displayOrder: 0,
|
||||
isActive: true,
|
||||
isLocked: false,
|
||||
});
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
tenantId: ''
|
||||
})
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
|
||||
const resetForm = () => {
|
||||
setFormData({
|
||||
|
|
@ -51,32 +55,33 @@ export function CategoryManagement({
|
|||
displayOrder: 0,
|
||||
isActive: true,
|
||||
isLocked: false,
|
||||
});
|
||||
setShowCreateForm(false);
|
||||
setEditingCategory(null);
|
||||
};
|
||||
tenantId: ''
|
||||
})
|
||||
setShowCreateForm(false)
|
||||
setEditingCategory(null)
|
||||
}
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (submitting) return;
|
||||
e.preventDefault()
|
||||
if (submitting) return
|
||||
|
||||
try {
|
||||
setSubmitting(true);
|
||||
setSubmitting(true)
|
||||
if (editingCategory) {
|
||||
await onUpdateCategory(editingCategory.id, formData);
|
||||
await onUpdateCategory(editingCategory.id, formData)
|
||||
} else {
|
||||
await onCreateCategory(formData);
|
||||
await onCreateCategory(formData)
|
||||
}
|
||||
resetForm();
|
||||
resetForm()
|
||||
} catch (error) {
|
||||
console.error('Error submitting form:', error);
|
||||
console.error('Error submitting form:', error)
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
setSubmitting(false)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleEdit = (category: ForumCategory) => {
|
||||
setEditingCategory(category);
|
||||
setEditingCategory(category)
|
||||
setFormData({
|
||||
name: category.name,
|
||||
slug: category.slug,
|
||||
|
|
@ -85,35 +90,40 @@ export function CategoryManagement({
|
|||
displayOrder: category.displayOrder,
|
||||
isActive: category.isActive,
|
||||
isLocked: category.isLocked,
|
||||
});
|
||||
setShowCreateForm(true);
|
||||
};
|
||||
tenantId: tenant.tenantId ?? ''
|
||||
})
|
||||
setShowCreateForm(true)
|
||||
}
|
||||
|
||||
const handleToggleActive = async (category: ForumCategory) => {
|
||||
try {
|
||||
await onUpdateCategoryActiveState(category.id);
|
||||
await onUpdateCategoryActiveState(category.id)
|
||||
} catch (error) {
|
||||
console.error('Error toggling category status:', error);
|
||||
console.error('Error toggling category status:', error)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleToggleLocked = async (category: ForumCategory) => {
|
||||
try {
|
||||
await onUpdateCategoryLockState(category.id);
|
||||
await onUpdateCategoryLockState(category.id)
|
||||
} catch (error) {
|
||||
console.error('Error toggling category lock:', error);
|
||||
console.error('Error toggling category lock:', error)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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 {
|
||||
await onDeleteCategory(id);
|
||||
await onDeleteCategory(id)
|
||||
} catch (error) {
|
||||
console.error('Error deleting category:', error);
|
||||
console.error('Error deleting category:', error)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
|
|
@ -158,7 +168,7 @@ export function CategoryManagement({
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Description</label>
|
||||
<textarea
|
||||
|
|
@ -169,7 +179,7 @@ export function CategoryManagement({
|
|||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Icon (Emoji)</label>
|
||||
|
|
@ -182,11 +192,15 @@ export function CategoryManagement({
|
|||
/>
|
||||
</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
|
||||
type="number"
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -211,7 +225,7 @@ export function CategoryManagement({
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex justify-end space-x-3">
|
||||
<button
|
||||
type="button"
|
||||
|
|
@ -239,7 +253,7 @@ export function CategoryManagement({
|
|||
<div className="px-6 py-4 border-b border-gray-200">
|
||||
<h3 className="text-lg font-semibold text-gray-900">Categories ({categories.length})</h3>
|
||||
</div>
|
||||
|
||||
|
||||
{loading ? (
|
||||
<div className="p-8 text-center">
|
||||
<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">
|
||||
<h4 className="text-lg font-semibold text-gray-900">{category.name}</h4>
|
||||
{!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 && (
|
||||
<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>
|
||||
<p className="text-gray-600 mb-2">{category.description}</p>
|
||||
|
|
@ -272,7 +290,7 @@ export function CategoryManagement({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
<button
|
||||
onClick={() => handleToggleActive(category)}
|
||||
|
|
@ -283,9 +301,13 @@ export function CategoryManagement({
|
|||
}`}
|
||||
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
|
||||
onClick={() => handleToggleLocked(category)}
|
||||
className={`p-2 rounded-lg transition-colors ${
|
||||
|
|
@ -295,9 +317,13 @@ export function CategoryManagement({
|
|||
}`}
|
||||
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
|
||||
onClick={() => handleEdit(category)}
|
||||
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" />
|
||||
</button>
|
||||
|
||||
|
||||
<button
|
||||
onClick={() => handleDelete(category.id)}
|
||||
className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors"
|
||||
|
|
@ -321,5 +347,5 @@ export function CategoryManagement({
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,18 @@ import { Plus, Edit2, Trash2, CheckCircle, Circle, Heart, Loader2 } from 'lucide
|
|||
import { ForumPost, ForumTopic } from '@/proxy/forum/forum'
|
||||
import ReactQuill from 'react-quill'
|
||||
import 'react-quill/dist/quill.snow.css'
|
||||
import { useStoreState } from '@/store/store'
|
||||
|
||||
interface PostManagementProps {
|
||||
posts: ForumPost[]
|
||||
topics: ForumTopic[]
|
||||
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>
|
||||
onDeletePost: (id: string) => Promise<void>
|
||||
onMarkPostAsAcceptedAnswer: (id: string) => Promise<void>
|
||||
|
|
@ -25,11 +31,14 @@ export function PostManagement({
|
|||
onMarkPostAsAcceptedAnswer,
|
||||
onUnmarkPostAsAcceptedAnswer,
|
||||
}: PostManagementProps) {
|
||||
const { tenant } = useStoreState((state) => state.auth)
|
||||
const [content, setContent] = useState('')
|
||||
const [showCreateForm, setShowCreateForm] = useState(false)
|
||||
const [editingPost, setEditingPost] = useState<ForumPost | null>(null)
|
||||
const [formData, setFormData] = useState({
|
||||
topicId: '',
|
||||
parentPostId: '',
|
||||
tenantId: '',
|
||||
isAcceptedAnswer: false,
|
||||
})
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
|
|
@ -37,6 +46,8 @@ export function PostManagement({
|
|||
const resetForm = () => {
|
||||
setFormData({
|
||||
topicId: '',
|
||||
parentPostId: '',
|
||||
tenantId: '',
|
||||
isAcceptedAnswer: false,
|
||||
})
|
||||
setShowCreateForm(false)
|
||||
|
|
@ -69,6 +80,8 @@ export function PostManagement({
|
|||
setEditingPost(post)
|
||||
setFormData({
|
||||
topicId: post.topicId,
|
||||
parentPostId: '',
|
||||
tenantId: tenant.tenantId ?? '',
|
||||
isAcceptedAnswer: post.isAcceptedAnswer,
|
||||
})
|
||||
setContent(post.content)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
Loader2,
|
||||
} from 'lucide-react'
|
||||
import { ForumCategory, ForumTopic } from '@/proxy/forum/forum'
|
||||
import { useStoreState } from '@/store/store'
|
||||
|
||||
interface TopicManagementProps {
|
||||
topics: ForumTopic[]
|
||||
|
|
@ -24,6 +25,7 @@ interface TopicManagementProps {
|
|||
categoryId: string
|
||||
isPinned?: boolean
|
||||
isLocked?: boolean
|
||||
tenantId?: string
|
||||
}) => Promise<void>
|
||||
onUpdateTopic: (id: string, topic: Partial<ForumTopic>) => Promise<void>
|
||||
onDeleteTopic: (id: string) => Promise<void>
|
||||
|
|
@ -49,6 +51,7 @@ export function TopicManagement({
|
|||
onMarkTopicAsSolved,
|
||||
onMarkTopicAsUnsolved,
|
||||
}: TopicManagementProps) {
|
||||
const { tenant } = useStoreState((state) => state.auth)
|
||||
const [showCreateForm, setShowCreateForm] = useState(false)
|
||||
const [editingTopic, setEditingTopic] = useState<ForumTopic | null>(null)
|
||||
const [formData, setFormData] = useState({
|
||||
|
|
@ -58,6 +61,7 @@ export function TopicManagement({
|
|||
isPinned: false,
|
||||
isLocked: false,
|
||||
isSolved: false,
|
||||
tenantId: '',
|
||||
})
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
|
||||
|
|
@ -69,6 +73,7 @@ export function TopicManagement({
|
|||
isPinned: false,
|
||||
isLocked: false,
|
||||
isSolved: false,
|
||||
tenantId: '',
|
||||
})
|
||||
setShowCreateForm(false)
|
||||
setEditingTopic(null)
|
||||
|
|
@ -102,6 +107,7 @@ export function TopicManagement({
|
|||
isPinned: topic.isPinned,
|
||||
isLocked: topic.isLocked,
|
||||
isSolved: topic.isSolved,
|
||||
tenantId: tenant.tenantId ?? ''
|
||||
})
|
||||
setShowCreateForm(true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,21 +2,23 @@ import React, { useState } from 'react';
|
|||
import { X } from 'lucide-react';
|
||||
import ReactQuill from 'react-quill';
|
||||
import 'react-quill/dist/quill.snow.css';
|
||||
import { useStoreState } from '@/store/store';
|
||||
|
||||
interface CreatePostModalProps {
|
||||
onClose: () => void;
|
||||
onSubmit: (data: { content: string }) => void;
|
||||
parentPostId?: string;
|
||||
onSubmit: (data: { content: string, parentPostId?: string, tenantId?: string }) => void;
|
||||
parentPostId: string
|
||||
}
|
||||
|
||||
export function CreatePostModal({ onClose, onSubmit, parentPostId }: CreatePostModalProps) {
|
||||
const [content, setContent] = useState('');
|
||||
const { tenant } = useStoreState((state) => state.auth)
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
const plainText = content.replace(/<[^>]+>/g, '').trim(); // HTML etiketlerini temizle
|
||||
if (plainText) {
|
||||
onSubmit({ content });
|
||||
onSubmit({ content, parentPostId, tenantId: tenant.tenantId });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
import React, { useState } from 'react';
|
||||
import { X } from 'lucide-react';
|
||||
import { useStoreState } from '@/store/store';
|
||||
|
||||
interface CreateTopicModalProps {
|
||||
onClose: () => void;
|
||||
onSubmit: (data: { title: string; content: string }) => void;
|
||||
onSubmit: (data: { title: string; content: string, tenantId?: string }) => void;
|
||||
}
|
||||
|
||||
export function CreateTopicModal({ onClose, onSubmit }: CreateTopicModalProps) {
|
||||
const [title, setTitle] = useState('');
|
||||
const [content, setContent] = useState('');
|
||||
const { tenant } = useStoreState((state) => state.auth)
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (title.trim() && content.trim()) {
|
||||
onSubmit({ title: title.trim(), content: content.trim() });
|
||||
onSubmit({ title: title.trim(), content: content.trim(), tenantId: tenant.tenantId });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,6 @@ export function ForumPostCard({
|
|||
isFirst = false,
|
||||
isLiked = false,
|
||||
}: PostCardProps) {
|
||||
const handleLike = () => {
|
||||
onLike(post.id, isFirst)
|
||||
}
|
||||
|
||||
const formatDate = (value: string | Date) => {
|
||||
const date = value instanceof Date ? value : new Date(value)
|
||||
if (isNaN(date.getTime())) return 'Invalid Date'
|
||||
|
|
@ -67,7 +63,10 @@ export function ForumPostCard({
|
|||
</div>
|
||||
|
||||
<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 className="flex items-center space-x-4">
|
||||
|
|
@ -83,13 +82,13 @@ export function ForumPostCard({
|
|||
<span>{post.likeCount}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
{!isFirst && (<button
|
||||
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"
|
||||
>
|
||||
<Reply className="w-4 h-4" />
|
||||
<span>Reply</span>
|
||||
</button>
|
||||
</button>)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { buildPostTree } from './utils'
|
|||
import { ForumPostCard } from './ForumPostCard'
|
||||
import { ForumCategoryCard } from './ForumCategoryCard'
|
||||
import { ForumTopicCard } from './ForumTopicCard'
|
||||
import { useStoreState } from '@/store/store'
|
||||
|
||||
interface ForumViewProps {
|
||||
categories: ForumCategory[]
|
||||
|
|
@ -21,8 +22,14 @@ interface ForumViewProps {
|
|||
categoryId: string
|
||||
isPinned?: boolean
|
||||
isLocked?: boolean
|
||||
tenantId?: string
|
||||
}) => Promise<void>
|
||||
onCreatePost: (post: {
|
||||
topicId: string
|
||||
content: string
|
||||
parentPostId?: string
|
||||
tenantId?: string
|
||||
}) => Promise<void>
|
||||
onCreatePost: (post: { topicId: string; content: string; parentPostId?: string }) => Promise<void>
|
||||
onLikePost: (id: string) => Promise<void>
|
||||
onUnlikePost: (id: string) => Promise<void>
|
||||
currentUserId: string
|
||||
|
|
@ -68,6 +75,7 @@ export function ForumView({
|
|||
|
||||
const [isSearchModalOpen, setIsSearchModalOpen] = useState(false)
|
||||
const [postLikeCounts, setPostLikeCounts] = useState<Record<string, number>>({})
|
||||
const { tenant } = useStoreState((state) => state.auth)
|
||||
|
||||
const handleSearchCategorySelect = (category: ForumCategory) => {
|
||||
if (onCategorySelect) onCategorySelect(category)
|
||||
|
|
@ -201,6 +209,7 @@ export function ForumView({
|
|||
categoryId: selectedCategory.id,
|
||||
isPinned: false,
|
||||
isLocked: false,
|
||||
tenantId: tenant.tenantId,
|
||||
})
|
||||
setShowCreateTopic(false)
|
||||
} catch (error) {
|
||||
|
|
@ -215,10 +224,11 @@ export function ForumView({
|
|||
await onCreatePost({
|
||||
topicId: selectedTopic.id,
|
||||
content: postData.content,
|
||||
parentPostId: replyToPostId, // buraya dikkat
|
||||
parentPostId: replyToPostId,
|
||||
tenantId: tenant.tenantId,
|
||||
})
|
||||
setShowCreatePost(false)
|
||||
setReplyToPostId(undefined) // temizle
|
||||
setReplyToPostId(undefined)
|
||||
} catch (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) => {
|
||||
setReplyToPostId(postId)
|
||||
setShowCreatePost(true)
|
||||
|
|
@ -446,9 +449,10 @@ export function ForumView({
|
|||
authorId: selectedTopic.authorId,
|
||||
authorName: selectedTopic.authorName,
|
||||
likeCount: postLikeCounts[selectedTopic.id] ?? selectedTopic.likeCount,
|
||||
isAcceptedAnswer: false,
|
||||
isAcceptedAnswer: false,
|
||||
parentPostId: undefined,
|
||||
creationTime: selectedTopic.creationTime,
|
||||
tenantId: selectedTopic.tenantId
|
||||
}}
|
||||
onLike={handleLike}
|
||||
onReply={handleReply}
|
||||
|
|
|
|||
|
|
@ -248,9 +248,10 @@ export function SearchModal({
|
|||
<div className="font-medium text-gray-900 text-sm line-clamp-1">
|
||||
{getTopicTitle(post.topicId)}
|
||||
</div>
|
||||
<div className="text-sm text-gray-600 line-clamp-2 mt-1">
|
||||
{post.content}
|
||||
</div>
|
||||
<div
|
||||
className="text-sm text-gray-600 line-clamp-2 mt-1"
|
||||
dangerouslySetInnerHTML={{ __html: post.content }}
|
||||
></div>
|
||||
<div className="text-xs text-gray-500 mt-1">
|
||||
by {post.authorName} • {formatDate(post.creationTime)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue