Forum değişiklikleri
This commit is contained in:
parent
b0311425ce
commit
4252cbf0f5
9 changed files with 212 additions and 140 deletions
|
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Authorization;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
|
|
@ -159,7 +158,8 @@ public class ForumAppService : PlatformAppService, IForumAppService
|
|||
input.Slug,
|
||||
input.Description,
|
||||
input.Icon,
|
||||
input.DisplayOrder
|
||||
input.DisplayOrder,
|
||||
input.TenantId
|
||||
)
|
||||
{
|
||||
IsActive = input.IsActive,
|
||||
|
|
@ -192,6 +192,7 @@ public class ForumAppService : PlatformAppService, IForumAppService
|
|||
{
|
||||
var category = await _categoryRepository.GetAsync(id);
|
||||
category.IsLocked = !category.IsLocked;
|
||||
|
||||
await _categoryRepository.UpdateAsync(category);
|
||||
return ObjectMapper.Map<ForumCategory, ForumCategoryDto>(category);
|
||||
}
|
||||
|
|
@ -201,6 +202,7 @@ public class ForumAppService : PlatformAppService, IForumAppService
|
|||
{
|
||||
var category = await _categoryRepository.GetAsync(id);
|
||||
category.IsActive = !category.IsActive;
|
||||
|
||||
await _categoryRepository.UpdateAsync(category);
|
||||
return ObjectMapper.Map<ForumCategory, ForumCategoryDto>(category);
|
||||
}
|
||||
|
|
@ -281,7 +283,8 @@ public class ForumAppService : PlatformAppService, IForumAppService
|
|||
input.Content,
|
||||
input.CategoryId,
|
||||
CurrentUser.Id.Value,
|
||||
CurrentUser.Name
|
||||
CurrentUser.Name,
|
||||
input.TenantId
|
||||
)
|
||||
{
|
||||
IsPinned = input.IsPinned,
|
||||
|
|
@ -380,7 +383,8 @@ public class ForumAppService : PlatformAppService, IForumAppService
|
|||
input.Content,
|
||||
CurrentUser.Id.Value,
|
||||
CurrentUser.Name,
|
||||
input.ParentPostId
|
||||
input.ParentPostId,
|
||||
input.TenantId
|
||||
);
|
||||
|
||||
await _postRepository.InsertAsync(post, autoSave: true);
|
||||
|
|
@ -473,24 +477,6 @@ public class ForumAppService : PlatformAppService, IForumAppService
|
|||
await _categoryRepository.UpdateAsync(category);
|
||||
}
|
||||
|
||||
// Like/Unlike topic
|
||||
public async Task<ForumTopicDto> LikeTopicAsync(Guid id)
|
||||
{
|
||||
var topic = await _topicRepository.GetAsync(id);
|
||||
topic.LikeCount++;
|
||||
await _topicRepository.UpdateAsync(topic);
|
||||
return ObjectMapper.Map<ForumTopic, ForumTopicDto>(topic);
|
||||
}
|
||||
|
||||
public async Task<ForumTopicDto> UnlikeTopicAsync(Guid id)
|
||||
{
|
||||
var topic = await _topicRepository.GetAsync(id);
|
||||
topic.LikeCount = Math.Max(0, topic.LikeCount - 1);
|
||||
await _topicRepository.UpdateAsync(topic);
|
||||
return ObjectMapper.Map<ForumTopic, ForumTopicDto>(topic);
|
||||
}
|
||||
|
||||
// Like/Unlike posts
|
||||
public async Task<ForumPostDto> LikePostAsync(Guid id)
|
||||
{
|
||||
var post = await _postRepository.GetAsync(id);
|
||||
|
|
@ -523,6 +509,96 @@ public class ForumAppService : PlatformAppService, IForumAppService
|
|||
return ObjectMapper.Map<ForumPost, ForumPostDto>(post);
|
||||
}
|
||||
|
||||
public async Task<ForumPostDto> MarkPostAsync(Guid id)
|
||||
{
|
||||
var post = await _postRepository.GetAsync(id);
|
||||
post.IsAcceptedAnswer = true;
|
||||
|
||||
await _postRepository.UpdateAsync(post);
|
||||
|
||||
return ObjectMapper.Map<ForumPost, ForumPostDto>(post);
|
||||
}
|
||||
|
||||
public async Task<ForumPostDto> UnmarkPostAsync(Guid id)
|
||||
{
|
||||
var post = await _postRepository.GetAsync(id);
|
||||
post.IsAcceptedAnswer = false;
|
||||
await _postRepository.UpdateAsync(post);
|
||||
|
||||
return ObjectMapper.Map<ForumPost, ForumPostDto>(post);
|
||||
}
|
||||
|
||||
// Like/Unlike topic
|
||||
public async Task<ForumTopicDto> LikeTopicAsync(Guid id)
|
||||
{
|
||||
var topic = await _topicRepository.GetAsync(id);
|
||||
topic.LikeCount++;
|
||||
|
||||
await _topicRepository.UpdateAsync(topic);
|
||||
return ObjectMapper.Map<ForumTopic, ForumTopicDto>(topic);
|
||||
}
|
||||
|
||||
public async Task<ForumTopicDto> UnlikeTopicAsync(Guid id)
|
||||
{
|
||||
var topic = await _topicRepository.GetAsync(id);
|
||||
topic.LikeCount = Math.Max(0, topic.LikeCount - 1);
|
||||
|
||||
await _topicRepository.UpdateAsync(topic);
|
||||
return ObjectMapper.Map<ForumTopic, ForumTopicDto>(topic);
|
||||
}
|
||||
|
||||
public async Task<ForumTopicDto> PinTopicAsync(Guid id)
|
||||
{
|
||||
var topic = await _topicRepository.GetAsync(id);
|
||||
topic.IsPinned = true;
|
||||
|
||||
await _topicRepository.UpdateAsync(topic);
|
||||
return ObjectMapper.Map<ForumTopic, ForumTopicDto>(topic);
|
||||
}
|
||||
|
||||
public async Task<ForumTopicDto> UnpinTopicAsync(Guid id)
|
||||
{
|
||||
var topic = await _topicRepository.GetAsync(id);
|
||||
topic.IsPinned = false;
|
||||
await _topicRepository.UpdateAsync(topic);
|
||||
return ObjectMapper.Map<ForumTopic, ForumTopicDto>(topic);
|
||||
}
|
||||
|
||||
public async Task<ForumTopicDto> LockTopicAsync(Guid id)
|
||||
{
|
||||
var topic = await _topicRepository.GetAsync(id);
|
||||
topic.IsLocked = true;
|
||||
|
||||
await _topicRepository.UpdateAsync(topic);
|
||||
return ObjectMapper.Map<ForumTopic, ForumTopicDto>(topic);
|
||||
}
|
||||
|
||||
public async Task<ForumTopicDto> UnlockTopicAsync(Guid id)
|
||||
{
|
||||
var topic = await _topicRepository.GetAsync(id);
|
||||
topic.IsLocked = false;
|
||||
await _topicRepository.UpdateAsync(topic);
|
||||
return ObjectMapper.Map<ForumTopic, ForumTopicDto>(topic);
|
||||
}
|
||||
|
||||
public async Task<ForumTopicDto> SolvedTopicAsync(Guid id)
|
||||
{
|
||||
var topic = await _topicRepository.GetAsync(id);
|
||||
topic.IsSolved = true;
|
||||
|
||||
await _topicRepository.UpdateAsync(topic);
|
||||
return ObjectMapper.Map<ForumTopic, ForumTopicDto>(topic);
|
||||
}
|
||||
|
||||
public async Task<ForumTopicDto> UnsolvedTopicAsync(Guid id)
|
||||
{
|
||||
var topic = await _topicRepository.GetAsync(id);
|
||||
topic.IsSolved = false;
|
||||
|
||||
await _topicRepository.UpdateAsync(topic);
|
||||
return ObjectMapper.Map<ForumTopic, ForumTopicDto>(topic);
|
||||
}
|
||||
|
||||
// Statistics
|
||||
public async Task<ForumStatsDto> GetForumStatsAsync()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<UserSecretsId>467bbc0f-83d0-40d0-a9f2-230c8620bdad</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
|
|||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||
}, {
|
||||
"url": "index.html",
|
||||
"revision": "0.mvu82hb2mqg"
|
||||
"revision": "0.m83v8d1s4bo"
|
||||
}], {});
|
||||
workbox.cleanupOutdatedCaches();
|
||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||
|
|
|
|||
|
|
@ -159,14 +159,6 @@ class ForumService {
|
|||
})
|
||||
}
|
||||
|
||||
// async toggleCategoryStatus(id: string): Promise<ForumCategory> {
|
||||
// const response = await apiService.fetchData<ForumCategory>({
|
||||
// url: `/api/app/forum/categories/${id}/toggle-status`,
|
||||
// method: 'POST',
|
||||
// })
|
||||
// return response.data
|
||||
// }
|
||||
|
||||
// Topics
|
||||
async getTopics(params: TopicListParams = {}): Promise<PaginatedResponse<ForumTopic>> {
|
||||
const response = await apiService.fetchData<PaginatedResponse<ForumTopic>>({
|
||||
|
|
@ -210,9 +202,25 @@ class ForumService {
|
|||
})
|
||||
}
|
||||
|
||||
async likeTopic(id: string): Promise<ForumTopic> {
|
||||
const response = await apiService.fetchData<ForumTopic>({
|
||||
url: `/api/app/forum/${id}/like-topic`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
}
|
||||
|
||||
async unlikeTopic(id: string): Promise<ForumTopic> {
|
||||
const response = await apiService.fetchData<ForumTopic>({
|
||||
url: `/api/app/forum/${id}/unlike-topic`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
}
|
||||
|
||||
async pinTopic(id: string): Promise<ForumTopic> {
|
||||
const response = await apiService.fetchData<ForumTopic>({
|
||||
url: `/api/app/forum/topics/${id}/pin`,
|
||||
url: `/api/app/forum/${id}/pin-topic`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
|
|
@ -220,7 +228,7 @@ class ForumService {
|
|||
|
||||
async unpinTopic(id: string): Promise<ForumTopic> {
|
||||
const response = await apiService.fetchData<ForumTopic>({
|
||||
url: `/api/app/forum/topics/${id}/unpin`,
|
||||
url: `/api/app/forum/${id}/unpin-topic`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
|
|
@ -228,7 +236,7 @@ class ForumService {
|
|||
|
||||
async lockTopic(id: string): Promise<ForumTopic> {
|
||||
const response = await apiService.fetchData<ForumTopic>({
|
||||
url: `/api/app/forum/topics/${id}/lock`,
|
||||
url: `/api/app/forum/${id}/lock-topic`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
|
|
@ -236,23 +244,23 @@ class ForumService {
|
|||
|
||||
async unlockTopic(id: string): Promise<ForumTopic> {
|
||||
const response = await apiService.fetchData<ForumTopic>({
|
||||
url: `/api/app/forum/topics/${id}/unlock`,
|
||||
url: `/api/app/forum/${id}/unlock-topic`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
}
|
||||
|
||||
async markTopicAsSolved(id: string): Promise<ForumTopic> {
|
||||
async solvedTopic(id: string): Promise<ForumTopic> {
|
||||
const response = await apiService.fetchData<ForumTopic>({
|
||||
url: `/api/app/forum/topics/${id}/mark-solved`,
|
||||
url: `/api/app/forum/${id}/solved-topic`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
}
|
||||
|
||||
async markTopicAsUnsolved(id: string): Promise<ForumTopic> {
|
||||
async unsolvedTopic(id: string): Promise<ForumTopic> {
|
||||
const response = await apiService.fetchData<ForumTopic>({
|
||||
url: `/api/app/forum/topics/${id}/mark-unsolved`,
|
||||
url: `/api/app/forum/${id}/unsolved-topic`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
|
|
@ -287,7 +295,7 @@ class ForumService {
|
|||
|
||||
async updatePost(id: string, data: Partial<CreatePostRequest>): Promise<ForumPost> {
|
||||
const response = await apiService.fetchData<ForumPost>({
|
||||
url: `/api/app/forum/posts/${id}`,
|
||||
url: `/api/app/forum/${id}/post`,
|
||||
method: 'PUT',
|
||||
data,
|
||||
})
|
||||
|
|
@ -296,7 +304,7 @@ class ForumService {
|
|||
|
||||
async deletePost(id: string): Promise<void> {
|
||||
await apiService.fetchData({
|
||||
url: `/api/app/forum/posts/${id}`,
|
||||
url: `/api/app/forum/${id}/post`,
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
|
@ -317,25 +325,9 @@ class ForumService {
|
|||
return response.data
|
||||
}
|
||||
|
||||
async likeTopic(id: string): Promise<ForumTopic> {
|
||||
const response = await apiService.fetchData<ForumTopic>({
|
||||
url: `/api/app/forum/${id}/like-topic`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
}
|
||||
|
||||
async unlikeTopic(id: string): Promise<ForumTopic> {
|
||||
const response = await apiService.fetchData<ForumTopic>({
|
||||
url: `/api/app/forum/${id}/unlike-topic`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
}
|
||||
|
||||
async markPostAsAcceptedAnswer(id: string): Promise<ForumPost> {
|
||||
const response = await apiService.fetchData<ForumPost>({
|
||||
url: `/api/app/forum/posts/${id}/mark-accepted`,
|
||||
url: `/api/app/forum/${id}/mark-post`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
|
|
@ -343,7 +335,7 @@ class ForumService {
|
|||
|
||||
async unmarkPostAsAcceptedAnswer(id: string): Promise<ForumPost> {
|
||||
const response = await apiService.fetchData<ForumPost>({
|
||||
url: `/api/app/forum/posts/${id}/unmark-accepted`,
|
||||
url: `/api/app/forum/${id}/unmark-post`,
|
||||
method: 'POST',
|
||||
})
|
||||
return response.data
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ export function Management() {
|
|||
unpinTopic,
|
||||
lockTopic,
|
||||
unlockTopic,
|
||||
markTopicAsSolved,
|
||||
markTopicAsUnsolved,
|
||||
solvedTopic,
|
||||
unsolvedTopic,
|
||||
createPost,
|
||||
updatePost,
|
||||
deletePost,
|
||||
|
|
@ -91,8 +91,8 @@ export function Management() {
|
|||
onUnpinTopic={(id) => unpinTopic(id).then(() => {})}
|
||||
onLockTopic={(id) => lockTopic(id).then(() => {})}
|
||||
onUnlockTopic={(id) => unlockTopic(id).then(() => {})}
|
||||
onMarkTopicAsSolved={(id) => markTopicAsSolved(id).then(() => {})}
|
||||
onMarkTopicAsUnsolved={(id) => markTopicAsUnsolved(id).then(() => {})}
|
||||
onMarkTopicAsSolved={(id) => solvedTopic(id).then(() => {})}
|
||||
onMarkTopicAsUnsolved={(id) => unsolvedTopic(id).then(() => {})}
|
||||
onCreatePost={(data) => createPost(data).then(() => {})}
|
||||
onUpdatePost={(id, data) => updatePost(id, data).then(() => {})}
|
||||
onDeletePost={(id) => deletePost(id).then(() => {})}
|
||||
|
|
|
|||
|
|
@ -1,56 +1,52 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Folder, MessageSquare, FileText, Plus, BarChart3 } from 'lucide-react';
|
||||
import { CategoryManagement } from './CategoryManagement';
|
||||
import { TopicManagement } from './TopicManagement';
|
||||
import { PostManagement } from './PostManagement';
|
||||
import { AdminStats } from './AdminStats';
|
||||
import { ForumCategory, ForumPost, ForumTopic } from '@/proxy/forum/forum';
|
||||
import React, { useState } from 'react'
|
||||
import { Folder, MessageSquare, FileText, Plus, BarChart3 } from 'lucide-react'
|
||||
import { CategoryManagement } from './CategoryManagement'
|
||||
import { TopicManagement } from './TopicManagement'
|
||||
import { PostManagement } from './PostManagement'
|
||||
import { ForumCategory, ForumPost, ForumTopic } from '@/proxy/forum/forum'
|
||||
import { AdminStats } from './Dashboard'
|
||||
|
||||
interface AdminViewProps {
|
||||
categories: ForumCategory[];
|
||||
topics: ForumTopic[];
|
||||
posts: ForumPost[];
|
||||
loading: boolean;
|
||||
categories: ForumCategory[]
|
||||
topics: ForumTopic[]
|
||||
posts: ForumPost[]
|
||||
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>;
|
||||
onUpdateCategoryLockState: (id: string) => Promise<void>;
|
||||
onUpdateCategoryActiveState: (id: string) => Promise<void>;
|
||||
onDeleteCategory: (id: string) => Promise<void>;
|
||||
name: string
|
||||
slug: string
|
||||
description: string
|
||||
icon: string
|
||||
displayOrder: number
|
||||
isActive: boolean
|
||||
isLocked: boolean
|
||||
}) => Promise<void>
|
||||
onUpdateCategory: (id: string, category: Partial<ForumCategory>) => Promise<void>
|
||||
onUpdateCategoryLockState: (id: string) => Promise<void>
|
||||
onUpdateCategoryActiveState: (id: string) => Promise<void>
|
||||
onDeleteCategory: (id: string) => Promise<void>
|
||||
onCreateTopic: (topic: {
|
||||
title: string;
|
||||
content: string;
|
||||
categoryId: string;
|
||||
isPinned?: boolean;
|
||||
isLocked?: boolean;
|
||||
}) => Promise<void>;
|
||||
onUpdateTopic: (id: string, topic: Partial<ForumTopic>) => Promise<void>;
|
||||
onDeleteTopic: (id: string) => Promise<void>;
|
||||
onPinTopic: (id: string) => Promise<void>;
|
||||
onUnpinTopic: (id: string) => Promise<void>;
|
||||
onLockTopic: (id: string) => Promise<void>;
|
||||
onUnlockTopic: (id: string) => Promise<void>;
|
||||
onMarkTopicAsSolved: (id: string) => Promise<void>;
|
||||
onMarkTopicAsUnsolved: (id: string) => Promise<void>;
|
||||
onCreatePost: (post: {
|
||||
topicId: string;
|
||||
content: string;
|
||||
parentPostId?: string;
|
||||
}) => Promise<void>;
|
||||
onUpdatePost: (id: string, post: Partial<ForumPost>) => Promise<void>;
|
||||
onDeletePost: (id: string) => Promise<void>;
|
||||
onMarkPostAsAcceptedAnswer: (id: string) => Promise<void>;
|
||||
onUnmarkPostAsAcceptedAnswer: (id: string) => Promise<void>;
|
||||
title: string
|
||||
content: string
|
||||
categoryId: string
|
||||
isPinned?: boolean
|
||||
isLocked?: boolean
|
||||
}) => Promise<void>
|
||||
onUpdateTopic: (id: string, topic: Partial<ForumTopic>) => Promise<void>
|
||||
onDeleteTopic: (id: string) => Promise<void>
|
||||
onPinTopic: (id: string) => Promise<void>
|
||||
onUnpinTopic: (id: string) => Promise<void>
|
||||
onLockTopic: (id: string) => Promise<void>
|
||||
onUnlockTopic: (id: string) => Promise<void>
|
||||
onMarkTopicAsSolved: (id: string) => Promise<void>
|
||||
onMarkTopicAsUnsolved: (id: string) => Promise<void>
|
||||
onCreatePost: (post: { topicId: string; content: string; parentPostId?: string }) => Promise<void>
|
||||
onUpdatePost: (id: string, post: Partial<ForumPost>) => Promise<void>
|
||||
onDeletePost: (id: string) => Promise<void>
|
||||
onMarkPostAsAcceptedAnswer: (id: string) => Promise<void>
|
||||
onUnmarkPostAsAcceptedAnswer: (id: string) => Promise<void>
|
||||
}
|
||||
|
||||
type AdminSection = 'stats' | 'categories' | 'topics' | 'posts';
|
||||
type AdminSection = 'stats' | 'categories' | 'topics' | 'posts'
|
||||
|
||||
export function AdminView({
|
||||
categories,
|
||||
|
|
@ -75,16 +71,16 @@ export function AdminView({
|
|||
onUpdatePost,
|
||||
onDeletePost,
|
||||
onMarkPostAsAcceptedAnswer,
|
||||
onUnmarkPostAsAcceptedAnswer
|
||||
onUnmarkPostAsAcceptedAnswer,
|
||||
}: AdminViewProps) {
|
||||
const [activeSection, setActiveSection] = useState<AdminSection>('stats');
|
||||
const [activeSection, setActiveSection] = useState<AdminSection>('stats')
|
||||
|
||||
const navigationItems = [
|
||||
{ id: 'stats' as AdminSection, label: 'Dashboard', icon: BarChart3 },
|
||||
{ id: 'categories' as AdminSection, label: 'Categories', icon: Folder },
|
||||
{ id: 'topics' as AdminSection, label: 'Topics', icon: MessageSquare },
|
||||
{ id: 'posts' as AdminSection, label: 'Posts', icon: FileText },
|
||||
];
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
|
|
@ -93,7 +89,7 @@ export function AdminView({
|
|||
<div className="lg:w-64 flex-shrink-0">
|
||||
<nav className="space-y-2">
|
||||
{navigationItems.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const Icon = item.icon
|
||||
return (
|
||||
<button
|
||||
key={item.id}
|
||||
|
|
@ -107,7 +103,7 @@ export function AdminView({
|
|||
<Icon className="w-5 h-5" />
|
||||
<span className="font-medium">{item.label}</span>
|
||||
</button>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</nav>
|
||||
</div>
|
||||
|
|
@ -162,5 +158,5 @@ export function AdminView({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
import React, { useState } from 'react'
|
||||
import { Plus, Edit2, Trash2, CheckCircle, Circle, Heart, Loader2 } from 'lucide-react'
|
||||
import { ForumPost, ForumTopic } from '@/proxy/forum/forum'
|
||||
import ReactQuill from 'react-quill'
|
||||
import 'react-quill/dist/quill.snow.css'
|
||||
|
||||
interface PostManagementProps {
|
||||
posts: ForumPost[]
|
||||
|
|
@ -23,11 +25,11 @@ export function PostManagement({
|
|||
onMarkPostAsAcceptedAnswer,
|
||||
onUnmarkPostAsAcceptedAnswer,
|
||||
}: PostManagementProps) {
|
||||
const [content, setContent] = useState('')
|
||||
const [showCreateForm, setShowCreateForm] = useState(false)
|
||||
const [editingPost, setEditingPost] = useState<ForumPost | null>(null)
|
||||
const [formData, setFormData] = useState({
|
||||
topicId: '',
|
||||
content: '',
|
||||
isAcceptedAnswer: false,
|
||||
})
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
|
|
@ -35,7 +37,6 @@ export function PostManagement({
|
|||
const resetForm = () => {
|
||||
setFormData({
|
||||
topicId: '',
|
||||
content: '',
|
||||
isAcceptedAnswer: false,
|
||||
})
|
||||
setShowCreateForm(false)
|
||||
|
|
@ -44,15 +45,18 @@ export function PostManagement({
|
|||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
if (submitting) return
|
||||
if (submitting || !content.trim()) return
|
||||
|
||||
try {
|
||||
setSubmitting(true)
|
||||
const data = { ...formData, content: content.trim() }
|
||||
|
||||
if (editingPost) {
|
||||
await onUpdatePost(editingPost.id, formData)
|
||||
await onUpdatePost(editingPost.id, data)
|
||||
} else {
|
||||
await onCreatePost(formData)
|
||||
await onCreatePost(data)
|
||||
}
|
||||
|
||||
resetForm()
|
||||
} catch (error) {
|
||||
console.error('Error submitting form:', error)
|
||||
|
|
@ -65,9 +69,9 @@ export function PostManagement({
|
|||
setEditingPost(post)
|
||||
setFormData({
|
||||
topicId: post.topicId,
|
||||
content: post.content,
|
||||
isAcceptedAnswer: post.isAcceptedAnswer,
|
||||
})
|
||||
setContent(post.content)
|
||||
setShowCreateForm(true)
|
||||
}
|
||||
|
||||
|
|
@ -151,12 +155,12 @@ export function PostManagement({
|
|||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Content</label>
|
||||
<textarea
|
||||
value={formData.content}
|
||||
onChange={(e) => setFormData({ ...formData, content: e.target.value })}
|
||||
rows={6}
|
||||
className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||
required
|
||||
<ReactQuill
|
||||
theme="snow"
|
||||
value={content}
|
||||
onChange={setContent}
|
||||
style={{ height: '400px', marginBottom: '50px' }}
|
||||
placeholder={'Write your message...'}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -230,7 +234,10 @@ export function PostManagement({
|
|||
Reply to:{' '}
|
||||
<span className="font-medium">{getTopicTitle(post.topicId)}</span>
|
||||
</p>
|
||||
<p className="text-gray-700 line-clamp-3">{post.content}</p>
|
||||
<p
|
||||
className="text-gray-700 line-clamp-3"
|
||||
dangerouslySetInnerHTML={{ __html: post.content }}
|
||||
></p>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between text-sm text-gray-500">
|
||||
|
|
|
|||
|
|
@ -248,9 +248,9 @@ export function useForumData() {
|
|||
}
|
||||
}
|
||||
|
||||
const markTopicAsSolved = async (id: string) => {
|
||||
const solvedTopic = async (id: string) => {
|
||||
try {
|
||||
const updatedTopic = await forumService.markTopicAsSolved(id)
|
||||
const updatedTopic = await forumService.solvedTopic(id)
|
||||
setTopics((prev) => prev.map((topic) => (topic.id === id ? updatedTopic : topic)))
|
||||
return updatedTopic
|
||||
} catch (err) {
|
||||
|
|
@ -260,9 +260,9 @@ export function useForumData() {
|
|||
}
|
||||
}
|
||||
|
||||
const markTopicAsUnsolved = async (id: string) => {
|
||||
const unsolvedTopic = async (id: string) => {
|
||||
try {
|
||||
const updatedTopic = await forumService.markTopicAsUnsolved(id)
|
||||
const updatedTopic = await forumService.unsolvedTopic(id)
|
||||
setTopics((prev) => prev.map((topic) => (topic.id === id ? updatedTopic : topic)))
|
||||
return updatedTopic
|
||||
} catch (err) {
|
||||
|
|
@ -432,8 +432,8 @@ export function useForumData() {
|
|||
unpinTopic,
|
||||
lockTopic,
|
||||
unlockTopic,
|
||||
markTopicAsSolved,
|
||||
markTopicAsUnsolved,
|
||||
solvedTopic,
|
||||
unsolvedTopic,
|
||||
|
||||
// Post operations
|
||||
createPost,
|
||||
|
|
|
|||
Loading…
Reference in a new issue