ActivityPanel entity düzenlemesi yapıldı
This commit is contained in:
parent
d77675108e
commit
f4106ab714
5 changed files with 88 additions and 86 deletions
|
|
@ -20,10 +20,10 @@ export interface ActivityItem {
|
|||
content: string
|
||||
creatorId?: string
|
||||
creationTime?: Date
|
||||
attachedFiles?: FileData[]
|
||||
attachedFiles?: ActivityFile[]
|
||||
}
|
||||
|
||||
export interface FileData {
|
||||
export interface ActivityFile {
|
||||
id?: string
|
||||
entityName: string
|
||||
entityId: string
|
||||
|
|
|
|||
|
|
@ -13,17 +13,15 @@ import { Activity } from '@/proxy/formActivity/models'
|
|||
|
||||
interface ActivityListProps {
|
||||
activities: Activity[]
|
||||
onDeleteNote?: (noteId: string) => void
|
||||
onDeleteActivity?: (activityId: string) => void
|
||||
onDeleteFile?: (fileId: string) => void
|
||||
onDeleteMessage?: (messageId: string) => void
|
||||
onDownloadFile?: (fileData: any) => void
|
||||
}
|
||||
|
||||
export const ActivityList: React.FC<ActivityListProps> = ({
|
||||
activities,
|
||||
onDeleteNote,
|
||||
onDeleteActivity,
|
||||
onDeleteFile,
|
||||
onDeleteMessage,
|
||||
onDownloadFile,
|
||||
}) => {
|
||||
const formatDate = (date: Date) => {
|
||||
|
|
@ -48,14 +46,7 @@ export const ActivityList: React.FC<ActivityListProps> = ({
|
|||
}
|
||||
|
||||
const handleDelete = (activity: Activity) => {
|
||||
switch (activity.type) {
|
||||
case 'note':
|
||||
onDeleteNote?.(activity.id)
|
||||
break
|
||||
case 'message':
|
||||
onDeleteMessage?.(activity.id)
|
||||
break
|
||||
}
|
||||
onDeleteActivity?.(activity.id)
|
||||
}
|
||||
|
||||
const handleDownloadFile = (fileData: any) => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import { Button, Input, Dialog, Select } from '@/components/ui'
|
||||
import { FaFileUpload, FaEnvelope, FaStickyNote, FaUsers, FaTimes, FaPlus, FaTrash, FaPaperclip } from 'react-icons/fa'
|
||||
import { FileData } from '@/proxy/formActivity/models'
|
||||
import { ActivityFile } from '@/proxy/formActivity/models'
|
||||
import { getUsers } from '@/services/identity.service'
|
||||
import { IdentityUserDto } from '@/proxy/admin/models'
|
||||
|
||||
|
|
@ -234,7 +234,7 @@ export const AddNoteModal: React.FC<AddNoteModalProps> = ({ isOpen, onClose, onS
|
|||
interface AddFileModalProps {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onUpload: (file: File) => Promise<FileData>
|
||||
onUpload: (file: File) => Promise<ActivityFile>
|
||||
}
|
||||
|
||||
export const AddFileModal: React.FC<AddFileModalProps> = ({ isOpen, onClose, onUpload }) => {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import {
|
|||
FaPlus,
|
||||
FaEnvelope,
|
||||
FaTimes,
|
||||
FaHistory,
|
||||
FaGripVertical,
|
||||
} from 'react-icons/fa'
|
||||
|
||||
|
|
@ -37,14 +36,11 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
|
|||
const buttonRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const {
|
||||
notes,
|
||||
messages,
|
||||
activities,
|
||||
addContent,
|
||||
sendMessage,
|
||||
deleteNote,
|
||||
deleteActivity,
|
||||
deleteFile,
|
||||
deleteMessage,
|
||||
addNote,
|
||||
sendMessage,
|
||||
} = useFormActivity(entityName, entityId)
|
||||
|
||||
const handleDownloadFile = (fileData: any) => {
|
||||
|
|
@ -55,7 +51,9 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
|
|||
link.click()
|
||||
}
|
||||
|
||||
const getTotalCount = () => notes.length + messages.length
|
||||
const getTotalCount = () => activities.length
|
||||
const getNoteCount = () => activities.filter(a => a.type === 'note').length
|
||||
const getMessageCount = () => activities.filter(a => a.type === 'message').length
|
||||
|
||||
// Mouse drag handlers
|
||||
const handleMouseDown = (e: React.MouseEvent) => {
|
||||
|
|
@ -181,19 +179,27 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
|
|||
>
|
||||
<div className="flex items-center gap-2">
|
||||
{isVisible ? <FaChevronRight /> : <FaChevronLeft />}
|
||||
<FaHistory />
|
||||
{getTotalCount() > 0 && <Badge content={getTotalCount()} />}
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Overlay - Click outside to close */}
|
||||
{isVisible && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black bg-opacity-25 z-20"
|
||||
onClick={onToggle}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Activity Panel */}
|
||||
<div
|
||||
className={`fixed right-0 top-0 h-full bg-white border-l border-gray-300 shadow-xl transform transition-transform duration-300 ease-in-out z-30 ${
|
||||
isVisible ? 'translate-x-0' : 'translate-x-full'
|
||||
}`}
|
||||
style={{ width: '400px' }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="flex flex-col h-full">
|
||||
{/* Header */}
|
||||
|
|
@ -254,7 +260,7 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
|
|||
: 'border-transparent text-gray-500 hover:text-gray-700'
|
||||
}`}
|
||||
>
|
||||
Notlar ({notes.length})
|
||||
Notlar ({getNoteCount()})
|
||||
</button>
|
||||
|
||||
<button
|
||||
|
|
@ -265,7 +271,7 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
|
|||
: 'border-transparent text-gray-500 hover:text-gray-700'
|
||||
}`}
|
||||
>
|
||||
Mesajlar ({messages.length})
|
||||
Mesajlar ({getMessageCount()})
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -275,9 +281,8 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
|
|||
{activeTab === 'activities' && (
|
||||
<ActivityList
|
||||
activities={activities}
|
||||
onDeleteNote={deleteNote}
|
||||
onDeleteActivity={deleteActivity}
|
||||
onDeleteFile={deleteFile}
|
||||
onDeleteMessage={deleteMessage}
|
||||
onDownloadFile={handleDownloadFile}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -285,9 +290,8 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
|
|||
{activeTab === 'notes' && (
|
||||
<ActivityList
|
||||
activities={activities.filter((a) => a.type === 'note')}
|
||||
onDeleteNote={deleteNote}
|
||||
onDeleteActivity={deleteActivity}
|
||||
onDeleteFile={deleteFile}
|
||||
onDeleteMessage={deleteMessage}
|
||||
onDownloadFile={handleDownloadFile}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -295,9 +299,8 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
|
|||
{activeTab === 'messages' && (
|
||||
<ActivityList
|
||||
activities={activities.filter((a) => a.type === 'message')}
|
||||
onDeleteNote={deleteNote}
|
||||
onDeleteActivity={deleteActivity}
|
||||
onDeleteFile={deleteFile}
|
||||
onDeleteMessage={deleteMessage}
|
||||
onDownloadFile={handleDownloadFile}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -309,7 +312,7 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
|
|||
<AddContentModal
|
||||
isOpen={showAddContent}
|
||||
onClose={() => setShowAddContent(false)}
|
||||
onSaveContent={addContent}
|
||||
onSaveContent={addNote}
|
||||
/>
|
||||
|
||||
<SendMessageModal
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
import { ActivityItem, FileData, Activity } from '@/proxy/formActivity/models'
|
||||
import { ActivityItem, ActivityFile, Activity } from '@/proxy/formActivity/models'
|
||||
import { useStoreState } from '@/store/store'
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
const STORAGE_PREFIX = 'form_activity_'
|
||||
|
||||
export const useFormActivity = (entityName: string, entityId: string) => {
|
||||
const [activityItems, setActivityItems] = useState<ActivityItem[]>([])
|
||||
const [files, setFiles] = useState<FileData[]>([])
|
||||
const [files, setFiles] = useState<ActivityFile[]>([])
|
||||
const [activities, setActivities] = useState<Activity[]>([])
|
||||
const { user } = useStoreState((state) => state.auth)
|
||||
|
||||
const storageKey = `${STORAGE_PREFIX}${entityName}_${entityId}`
|
||||
|
||||
|
|
@ -23,7 +25,7 @@ export const useFormActivity = (entityName: string, entityId: string) => {
|
|||
const oldMessages = parsed.messages || []
|
||||
const combinedActivityItems: ActivityItem[] = [
|
||||
...oldNotes.map((note: any) => ({ ...note, type: 'note' as const })),
|
||||
...oldMessages.map((message: any) => ({ ...message, type: 'message' as const }))
|
||||
...oldMessages.map((message: any) => ({ ...message, type: 'message' as const })),
|
||||
]
|
||||
setActivityItems(parsed.activityItems || combinedActivityItems || [])
|
||||
setFiles(parsed.files || [])
|
||||
|
|
@ -38,7 +40,7 @@ export const useFormActivity = (entityName: string, entityId: string) => {
|
|||
const allActivities: Activity[] = []
|
||||
|
||||
// Convert all activity items to activities
|
||||
activityItems.forEach(item => {
|
||||
activityItems.forEach((item) => {
|
||||
allActivities.push({
|
||||
id: item.id || `${item.type}_${Date.now()}`,
|
||||
type: item.type,
|
||||
|
|
@ -47,12 +49,14 @@ export const useFormActivity = (entityName: string, entityId: string) => {
|
|||
recipientUserName: item.recipientUserName,
|
||||
creationTime: item.creationTime || new Date(),
|
||||
creatorId: item.creatorId || 'Bilinmeyen',
|
||||
data: item
|
||||
data: item,
|
||||
})
|
||||
})
|
||||
|
||||
// Sort by timestamp (newest first)
|
||||
allActivities.sort((a, b) => new Date(b.creationTime).getTime() - new Date(a.creationTime).getTime())
|
||||
allActivities.sort(
|
||||
(a, b) => new Date(b.creationTime).getTime() - new Date(a.creationTime).getTime(),
|
||||
)
|
||||
setActivities(allActivities)
|
||||
}, [activityItems, files])
|
||||
|
||||
|
|
@ -62,27 +66,27 @@ export const useFormActivity = (entityName: string, entityId: string) => {
|
|||
|
||||
const dataToSave = {
|
||||
activityItems,
|
||||
files
|
||||
files,
|
||||
}
|
||||
localStorage.setItem(storageKey, JSON.stringify(dataToSave))
|
||||
}, [activityItems, files, storageKey])
|
||||
|
||||
const addNote = (subject: string, content: string) => {
|
||||
const addActivity = (subject: string, content: string, type: 'note' | 'message' = 'note') => {
|
||||
const newActivityItem: ActivityItem = {
|
||||
id: `note_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
||||
type: 'note',
|
||||
id: `${type}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
||||
type,
|
||||
entityName,
|
||||
entityId,
|
||||
subject,
|
||||
content,
|
||||
creatorId: 'Mevcut Kullanıcı', // Bu gerçek implementasyonda authentication'dan gelecek
|
||||
creationTime: new Date()
|
||||
creatorId: user.id,
|
||||
creationTime: new Date(),
|
||||
}
|
||||
setActivityItems(prev => [...prev, newActivityItem])
|
||||
setActivityItems((prev) => [...prev, newActivityItem])
|
||||
return newActivityItem
|
||||
}
|
||||
|
||||
const addContent = async (subject: string, content: string, files: File[]) => {
|
||||
const addNote = async (subject: string, content: string, files: File[]) => {
|
||||
const timestamp = new Date()
|
||||
const baseId = `content_${timestamp.getTime()}_${Math.random().toString(36).substr(2, 9)}`
|
||||
|
||||
|
|
@ -94,19 +98,19 @@ export const useFormActivity = (entityName: string, entityId: string) => {
|
|||
entityId,
|
||||
subject,
|
||||
content: content || (files.length > 0 ? `${files.length} dosya eklendi` : ''),
|
||||
creatorId: 'Mevcut Kullanıcı',
|
||||
creatorId: user.id,
|
||||
creationTime: timestamp,
|
||||
attachedFiles: [] // Dosyaları buraya ekleyeceğiz
|
||||
attachedFiles: [], // Dosyaları buraya ekleyeceğiz
|
||||
}
|
||||
|
||||
// Dosyaları yükle ve note'a attach et
|
||||
const uploadedFiles: FileData[] = []
|
||||
const uploadedFiles: ActivityFile[] = []
|
||||
for (const file of files) {
|
||||
try {
|
||||
const uploadedFile = await new Promise<FileData>((resolve, reject) => {
|
||||
const uploadedFile = await new Promise<ActivityFile>((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = () => {
|
||||
const newFile: FileData = {
|
||||
const newFile: ActivityFile = {
|
||||
id: `${baseId}_file_${Math.random().toString(36).substr(2, 9)}`,
|
||||
entityName,
|
||||
entityId,
|
||||
|
|
@ -114,8 +118,8 @@ export const useFormActivity = (entityName: string, entityId: string) => {
|
|||
fileSize: file.size,
|
||||
fileType: file.type,
|
||||
filePath: `uploads/${entityName}/${entityId}/${file.name}`,
|
||||
creatorId: 'Mevcut Kullanıcı',
|
||||
creationTime: timestamp
|
||||
creatorId: user.id,
|
||||
creationTime: timestamp,
|
||||
}
|
||||
resolve(newFile)
|
||||
}
|
||||
|
|
@ -132,22 +136,22 @@ export const useFormActivity = (entityName: string, entityId: string) => {
|
|||
newActivityItem.attachedFiles = uploadedFiles
|
||||
|
||||
// Activity Item'ı kaydet
|
||||
setActivityItems(prev => [...prev, newActivityItem])
|
||||
setActivityItems((prev) => [...prev, newActivityItem])
|
||||
|
||||
// Dosyaları ayrı ayrı da kaydet (eski sistem uyumluluğu için)
|
||||
if (uploadedFiles.length > 0) {
|
||||
setFiles(prev => [...prev, ...uploadedFiles])
|
||||
setFiles((prev) => [...prev, ...uploadedFiles])
|
||||
}
|
||||
|
||||
return newActivityItem
|
||||
}
|
||||
|
||||
const addFile = (file: File) => {
|
||||
return new Promise<FileData>((resolve, reject) => {
|
||||
return new Promise<ActivityFile>((resolve, reject) => {
|
||||
// Simulate file upload - gerçek implementasyonda API call yapılacak
|
||||
const reader = new FileReader()
|
||||
reader.onload = () => {
|
||||
const newFile: FileData = {
|
||||
const newFile: ActivityFile = {
|
||||
id: `file_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
||||
entityName,
|
||||
entityId,
|
||||
|
|
@ -155,10 +159,10 @@ export const useFormActivity = (entityName: string, entityId: string) => {
|
|||
fileSize: file.size,
|
||||
fileType: file.type,
|
||||
filePath: `uploads/${entityName}/${entityId}/${file.name}`, // Simulated path
|
||||
creatorId: 'Mevcut Kullanıcı',
|
||||
creationTime: new Date()
|
||||
creatorId: user.id,
|
||||
creationTime: new Date(),
|
||||
}
|
||||
setFiles(prev => [...prev, newFile])
|
||||
setFiles((prev) => [...prev, newFile])
|
||||
resolve(newFile)
|
||||
}
|
||||
reader.onerror = () => reject(reader.error)
|
||||
|
|
@ -166,8 +170,23 @@ export const useFormActivity = (entityName: string, entityId: string) => {
|
|||
})
|
||||
}
|
||||
|
||||
const sendMessage = (recipients: Array<{ value: string, label: string, email?: string }>, subject: string, content: string) => {
|
||||
const newMessageItems: ActivityItem[] = recipients.map(recipient => ({
|
||||
|
||||
|
||||
const deleteActivity = (itemId: string) => {
|
||||
setActivityItems((prev) => prev.filter((item) => item.id !== itemId))
|
||||
}
|
||||
|
||||
const deleteFile = (fileId: string) => {
|
||||
setFiles((prev) => prev.filter((file) => file.id !== fileId))
|
||||
}
|
||||
|
||||
const sendMessage = (
|
||||
recipients: Array<{ value: string; label: string; email?: string }>,
|
||||
subject: string,
|
||||
content: string,
|
||||
) => {
|
||||
// Her recipient için ayrı mesaj aktivitesi oluştur
|
||||
const newMessageItems: ActivityItem[] = recipients.map((recipient) => ({
|
||||
id: `message_${Date.now()}_${Math.random().toString(36).substr(2, 9)}_${recipient.value}`,
|
||||
type: 'message' as const,
|
||||
entityName,
|
||||
|
|
@ -176,37 +195,26 @@ export const useFormActivity = (entityName: string, entityId: string) => {
|
|||
recipientUserName: recipient.label,
|
||||
subject,
|
||||
content,
|
||||
creatorId: 'Mevcut Kullanıcı',
|
||||
creationTime: new Date()
|
||||
creatorId: user.id,
|
||||
creationTime: new Date(),
|
||||
}))
|
||||
setActivityItems(prev => [...prev, ...newMessageItems])
|
||||
|
||||
// Tüm mesajları activityItems'a ekle
|
||||
setActivityItems((prev) => [...prev, ...newMessageItems])
|
||||
return newMessageItems
|
||||
}
|
||||
|
||||
const deleteActivityItem = (itemId: string) => {
|
||||
setActivityItems(prev => prev.filter(item => item.id !== itemId))
|
||||
}
|
||||
|
||||
const deleteFile = (fileId: string) => {
|
||||
setFiles(prev => prev.filter(file => file.id !== fileId))
|
||||
}
|
||||
|
||||
// Geriye dönük uyumluluk için
|
||||
const notes = activityItems.filter(item => item.type === 'note')
|
||||
const messages = activityItems.filter(item => item.type === 'message')
|
||||
|
||||
return {
|
||||
activityItems,
|
||||
notes,
|
||||
files,
|
||||
messages,
|
||||
activities,
|
||||
// Ana aktivite fonksiyonları
|
||||
addActivity,
|
||||
deleteActivity,
|
||||
addNote,
|
||||
addFile,
|
||||
addContent,
|
||||
sendMessage,
|
||||
deleteNote: deleteActivityItem, // Not silme için
|
||||
// Dosya işlemleri
|
||||
addFile,
|
||||
deleteFile,
|
||||
deleteMessage: deleteActivityItem // Mesaj silme için
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue