LocalStorage kaldırıldı ama henüz End pointler ile doğru çalışmıyor

This commit is contained in:
Sedat ÖZTÜRK 2025-10-13 17:58:08 +03:00
parent 87d155a04b
commit 5e4726c9be
2 changed files with 275 additions and 168 deletions

View file

@ -37,6 +37,7 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
const { const {
activities, activities,
loading,
deleteActivity, deleteActivity,
deleteFile, deleteFile,
addNote, addNote,
@ -279,31 +280,40 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
{/* Content */} {/* Content */}
<div className="flex-1 overflow-y-auto p-4"> <div className="flex-1 overflow-y-auto p-4">
{activeTab === 'activities' && ( {loading ? (
<ActivityList <div className="flex items-center justify-center h-32">
activities={activities} <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
onDeleteActivity={deleteActivity} <span className="ml-2 text-gray-600">Yükleniyor...</span>
onDeleteFile={deleteFile} </div>
onDownloadFile={handleDownloadFile} ) : (
/> <>
)} {activeTab === 'activities' && (
<ActivityList
activities={activities}
onDeleteActivity={deleteActivity}
onDeleteFile={deleteFile}
onDownloadFile={handleDownloadFile}
/>
)}
{activeTab === 'notes' && ( {activeTab === 'notes' && (
<ActivityList <ActivityList
activities={activities.filter((a) => a.type === 'note')} activities={activities.filter((a) => a.type === 'note')}
onDeleteActivity={deleteActivity} onDeleteActivity={deleteActivity}
onDeleteFile={deleteFile} onDeleteFile={deleteFile}
onDownloadFile={handleDownloadFile} onDownloadFile={handleDownloadFile}
/> />
)} )}
{activeTab === 'messages' && ( {activeTab === 'messages' && (
<ActivityList <ActivityList
activities={activities.filter((a) => a.type === 'message')} activities={activities.filter((a) => a.type === 'message')}
onDeleteActivity={deleteActivity} onDeleteActivity={deleteActivity}
onDeleteFile={deleteFile} onDeleteFile={deleteFile}
onDownloadFile={handleDownloadFile} onDownloadFile={handleDownloadFile}
/> />
)}
</>
)} )}
</div> </div>
</div> </div>

View file

@ -1,40 +1,81 @@
import { ActivityItem, ActivityFile, Activity } from '@/proxy/formActivity/models' import { ActivityItem, ActivityFile, Activity } from '@/proxy/formActivity/models'
import { ActivityDto, ActivityItemDto, ActivityFileDto } from '@/proxy/activity/models'
import { activityService } from '@/services/activity.service'
import { useStoreState } from '@/store/store' import { useStoreState } from '@/store/store'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
const STORAGE_PREFIX = 'form_activity_'
export const useFormActivity = (entityName: string, entityId: string) => { export const useFormActivity = (entityName: string, entityId: string) => {
const [activityItems, setActivityItems] = useState<ActivityItem[]>([]) const [activityItems, setActivityItems] = useState<ActivityItem[]>([])
const [files, setFiles] = useState<ActivityFile[]>([]) const [files, setFiles] = useState<ActivityFile[]>([])
const [activities, setActivities] = useState<Activity[]>([]) const [activities, setActivities] = useState<Activity[]>([])
const [loading, setLoading] = useState(false)
const { user } = useStoreState((state) => state.auth) const { user } = useStoreState((state) => state.auth)
const storageKey = `${STORAGE_PREFIX}${entityName}_${entityId}` // Load data from API on component mount
// Load data from localStorage on component mount
useEffect(() => { useEffect(() => {
if (!entityName || !entityId) return if (!entityName || !entityId) return
loadActivitiesFromAPI()
const savedData = localStorage.getItem(storageKey)
if (savedData) {
try {
const parsed = JSON.parse(savedData)
// Eski veriyi yeni yapıya dönüştür
const oldNotes = parsed.notes || []
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 })),
]
setActivityItems(parsed.activityItems || combinedActivityItems || [])
setFiles(parsed.files || [])
} catch (error) {
console.error('Failed to load activity data:', error)
}
}
}, [entityName, entityId]) }, [entityName, entityId])
const loadActivitiesFromAPI = async () => {
try {
setLoading(true)
// Tüm ActivityItem'ları al
const items = await activityService.getItems()
// EntityName ve EntityId ile filtrele
const filteredItems = items.filter(
item => item.entityName === entityName && item.entityId === entityId
)
// DTO'dan ActivityItem'a dönüştür
const convertedItems: ActivityItem[] = filteredItems.map(dto => ({
id: dto.id,
type: (dto.type as 'note' | 'message') || 'note',
entityName: dto.entityName || entityName,
entityId: dto.entityId || entityId,
recipientUserId: dto.recipientUserId,
recipientUserName: dto.recipientUserName,
subject: dto.subject || '',
content: dto.content || '',
creatorId: dto.creatorId || user.id,
creationTime: dto.creationTime ? new Date(dto.creationTime) : new Date(),
attachedFiles: []
}))
// Her ActivityItem için dosyaları yükle
for (const item of convertedItems) {
if (item.id) {
try {
const itemFiles = await activityService.getFiles(item.id)
const convertedFiles: ActivityFile[] = itemFiles.map(fileDto => ({
id: fileDto.id,
entityName: fileDto.entityName || entityName,
entityId: fileDto.entityId || entityId,
fileName: fileDto.fileName || '',
fileSize: fileDto.fileSize || 0,
fileType: fileDto.fileType || '',
filePath: fileDto.filePath || '',
creatorId: fileDto.creatorId || user.id,
creationTime: fileDto.creationTime ? new Date(fileDto.creationTime) : new Date(),
}))
item.attachedFiles = convertedFiles
setFiles(prev => [...prev, ...convertedFiles])
} catch (error) {
console.error('Failed to load files for activity item:', item.id, error)
}
}
}
setActivityItems(convertedItems)
} catch (error) {
console.error('Failed to load activities from API:', error)
} finally {
setLoading(false)
}
}
// Update activities when data changes // Update activities when data changes
useEffect(() => { useEffect(() => {
const allActivities: Activity[] = [] const allActivities: Activity[] = []
@ -60,161 +101,217 @@ export const useFormActivity = (entityName: string, entityId: string) => {
setActivities(allActivities) setActivities(allActivities)
}, [activityItems, files]) }, [activityItems, files])
// Save to localStorage whenever data changes
useEffect(() => {
if (!entityName || !entityId) return
const dataToSave = {
activityItems,
files,
}
localStorage.setItem(storageKey, JSON.stringify(dataToSave))
}, [activityItems, files, storageKey])
const addActivity = (subject: string, content: string, type: 'note' | 'message' = 'note') => {
const newActivityItem: ActivityItem = {
id: `${type}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
type,
entityName,
entityId,
subject,
content,
creatorId: user.id,
creationTime: new Date(),
}
setActivityItems((prev) => [...prev, newActivityItem])
return newActivityItem
}
const addNote = async (subject: string, content: string, files: File[]) => { const addNote = async (subject: string, content: string, files: File[]) => {
const timestamp = new Date() try {
const baseId = `content_${timestamp.getTime()}_${Math.random().toString(36).substr(2, 9)}` setLoading(true)
// Hem not hem de dosya varsa veya sadece biri varsa tek bir note aktivitesi oluştur // Önce Activity oluştur
const newActivityItem: ActivityItem = { const activityDto: Partial<ActivityDto> = {
id: baseId, type: 'note',
type: 'note', subject: subject || 'Not',
entityName, content: content || (files.length > 0 ? `${files.length} dosya eklendi` : ''),
entityId, }
subject,
content: content || (files.length > 0 ? `${files.length} dosya eklendi` : ''), const createdActivity = await activityService.create(activityDto as ActivityDto)
creatorId: user.id,
creationTime: timestamp,
attachedFiles: [], // Dosyaları buraya ekleyeceğiz
}
// Dosyaları yükle ve note'a attach et // ActivityItem oluştur
const uploadedFiles: ActivityFile[] = [] const activityItemDto: Partial<ActivityItemDto> = {
for (const file of files) { activityId: createdActivity.id,
try { type: 'note',
const uploadedFile = await new Promise<ActivityFile>((resolve, reject) => { entityName,
const reader = new FileReader() entityId,
reader.onload = () => { subject: subject || 'Not',
const newFile: ActivityFile = { content: content || (files.length > 0 ? `${files.length} dosya eklendi` : ''),
id: `${baseId}_file_${Math.random().toString(36).substr(2, 9)}`, }
entityName,
entityId, const createdActivityItem = await activityService.createItem(activityItemDto as ActivityItemDto)
fileName: file.name,
fileSize: file.size, // Dosyaları yükle
fileType: file.type, const uploadedFiles: ActivityFile[] = []
filePath: `uploads/${entityName}/${entityId}/${file.name}`, for (const file of files) {
creatorId: user.id, try {
creationTime: timestamp, const activityFileDto: Partial<ActivityFileDto> = {
} activityItemId: createdActivityItem.id,
resolve(newFile) entityName,
entityId,
fileName: file.name,
fileSize: file.size,
fileType: file.type,
filePath: `uploads/${entityName}/${entityId}/${file.name}`,
} }
reader.onerror = () => reject(reader.error)
reader.readAsDataURL(file)
})
uploadedFiles.push(uploadedFile)
} catch (error) {
console.error('File upload failed:', error)
}
}
// Note'a dosyaları ekle const createdFile = await activityService.uploadFile(activityFileDto as ActivityFileDto)
newActivityItem.attachedFiles = uploadedFiles
const newFile: ActivityFile = {
// Activity Item'ı kaydet id: createdFile.id,
setActivityItems((prev) => [...prev, newActivityItem]) entityName: createdFile.entityName || entityName,
entityId: createdFile.entityId || entityId,
// Dosyaları ayrı ayrı da kaydet (eski sistem uyumluluğu için) fileName: createdFile.fileName || file.name,
if (uploadedFiles.length > 0) { fileSize: createdFile.fileSize || file.size,
setFiles((prev) => [...prev, ...uploadedFiles]) fileType: createdFile.fileType || file.type,
} filePath: createdFile.filePath || '',
creatorId: createdFile.creatorId || user.id,
return newActivityItem creationTime: createdFile.creationTime ? new Date(createdFile.creationTime) : new Date(),
} }
const addFile = (file: File) => { uploadedFiles.push(newFile)
return new Promise<ActivityFile>((resolve, reject) => { } catch (error) {
// Simulate file upload - gerçek implementasyonda API call yapılacak console.error('File upload failed:', error)
const reader = new FileReader()
reader.onload = () => {
const newFile: ActivityFile = {
id: `file_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
entityName,
entityId,
fileName: file.name,
fileSize: file.size,
fileType: file.type,
filePath: `uploads/${entityName}/${entityId}/${file.name}`, // Simulated path
creatorId: user.id,
creationTime: new Date(),
} }
setFiles((prev) => [...prev, newFile])
resolve(newFile)
} }
reader.onerror = () => reject(reader.error)
reader.readAsDataURL(file) // Yeni ActivityItem'ı local state'e ekle
}) const newActivityItem: ActivityItem = {
id: createdActivityItem.id,
type: 'note',
entityName,
entityId,
subject: createdActivityItem.subject || '',
content: createdActivityItem.content || '',
creatorId: createdActivityItem.creatorId || user.id,
creationTime: createdActivityItem.creationTime ? new Date(createdActivityItem.creationTime) : new Date(),
attachedFiles: uploadedFiles
}
setActivityItems((prev) => [...prev, newActivityItem])
if (uploadedFiles.length > 0) {
setFiles((prev) => [...prev, ...uploadedFiles])
}
return newActivityItem
} catch (error) {
console.error('Failed to create note:', error)
throw error
} finally {
setLoading(false)
}
} }
const deleteActivity = (itemId: string) => {
setActivityItems((prev) => prev.filter((item) => item.id !== itemId))
const deleteActivity = async (itemId: string) => {
try {
// API'dan ActivityItem'ı sil
await activityService.deleteItem(itemId)
// Local state'ten kaldır
setActivityItems((prev) => prev.filter((item) => item.id !== itemId))
// İlgili dosyaları da kaldır
setFiles((prev) => prev.filter((file) =>
!(file as any).activityItemId || (file as any).activityItemId !== itemId
))
} catch (error) {
console.error('Failed to delete activity:', error)
throw error
}
} }
const deleteFile = (fileId: string) => { const deleteFile = async (fileId: string) => {
setFiles((prev) => prev.filter((file) => file.id !== fileId)) try {
// API'dan ActivityFile'ı sil
await activityService.deleteFile(fileId)
// Local state'ten kaldır
setFiles((prev) => prev.filter((file) => file.id !== fileId))
// ActivityItem'dan da kaldır
setActivityItems((prev) =>
prev.map(item => ({
...item,
attachedFiles: item.attachedFiles?.filter(file => file.id !== fileId) || []
}))
)
} catch (error) {
console.error('Failed to delete file:', error)
throw error
}
} }
const sendMessage = ( const sendMessage = async (
recipients: Array<{ value: string; label: string; email?: string }>, recipients: Array<{ value: string; label: string; email?: string }>,
subject: string, subject: string,
content: string, content: string,
) => { ) => {
// Her recipient için ayrı mesaj aktivitesi oluştur try {
const newMessageItems: ActivityItem[] = recipients.map((recipient) => ({ setLoading(true)
id: `message_${Date.now()}_${Math.random().toString(36).substr(2, 9)}_${recipient.value}`, const newMessageItems: ActivityItem[] = []
type: 'message' as const,
entityName, // Her recipient için ayrı mesaj aktivitesi oluştur
entityId, for (const recipient of recipients) {
recipientUserId: recipient.value, try {
recipientUserName: recipient.label, // Activity oluştur
subject, const activityDto: Partial<ActivityDto> = {
content, type: 'message',
creatorId: user.id, subject,
creationTime: new Date(), content,
})) recipientUserName: recipient.label,
}
// Tüm mesajları activityItems'a ekle
setActivityItems((prev) => [...prev, ...newMessageItems]) const createdActivity = await activityService.create(activityDto as ActivityDto)
return newMessageItems
// ActivityItem oluştur
const activityItemDto: Partial<ActivityItemDto> = {
activityId: createdActivity.id,
type: 'message',
entityName,
entityId,
recipientUserId: recipient.value,
recipientUserName: recipient.label,
subject,
content,
}
const createdActivityItem = await activityService.createItem(activityItemDto as ActivityItemDto)
const newMessageItem: ActivityItem = {
id: createdActivityItem.id,
type: 'message',
entityName,
entityId,
recipientUserId: createdActivityItem.recipientUserId,
recipientUserName: createdActivityItem.recipientUserName,
subject: createdActivityItem.subject || '',
content: createdActivityItem.content || '',
creatorId: createdActivityItem.creatorId || user.id,
creationTime: createdActivityItem.creationTime ? new Date(createdActivityItem.creationTime) : new Date(),
}
newMessageItems.push(newMessageItem)
} catch (error) {
console.error('Failed to send message to recipient:', recipient.label, error)
}
}
// Tüm mesajları activityItems'a ekle
setActivityItems((prev) => [...prev, ...newMessageItems])
return newMessageItems
} catch (error) {
console.error('Failed to send messages:', error)
throw error
} finally {
setLoading(false)
}
} }
return { return {
activityItems, activityItems,
files, files,
activities, activities,
loading,
// Ana aktivite fonksiyonları // Ana aktivite fonksiyonları
addActivity,
deleteActivity, deleteActivity,
addNote, addNote,
sendMessage, sendMessage,
// Dosya işlemleri // Dosya işlemleri
addFile,
deleteFile, deleteFile,
// Veri yenileme
refreshActivities: loadActivitiesFromAPI,
} }
} }