LocalStorage kaldırıldı ama henüz End pointler ile doğru çalışmıyor
This commit is contained in:
parent
87d155a04b
commit
5e4726c9be
2 changed files with 275 additions and 168 deletions
|
|
@ -37,6 +37,7 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
|
||||||
|
|
||||||
const {
|
const {
|
||||||
activities,
|
activities,
|
||||||
|
loading,
|
||||||
deleteActivity,
|
deleteActivity,
|
||||||
deleteFile,
|
deleteFile,
|
||||||
addNote,
|
addNote,
|
||||||
|
|
@ -279,6 +280,13 @@ 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">
|
||||||
|
{loading ? (
|
||||||
|
<div className="flex items-center justify-center h-32">
|
||||||
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
|
||||||
|
<span className="ml-2 text-gray-600">Yükleniyor...</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
{activeTab === 'activities' && (
|
{activeTab === 'activities' && (
|
||||||
<ActivityList
|
<ActivityList
|
||||||
activities={activities}
|
activities={activities}
|
||||||
|
|
@ -305,6 +313,8 @@ export const FormActivityPanel: React.FC<ActivityPanelProps> = ({
|
||||||
onDownloadFile={handleDownloadFile}
|
onDownloadFile={handleDownloadFile}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
subject: subject || 'Not',
|
||||||
|
content: content || (files.length > 0 ? `${files.length} dosya eklendi` : ''),
|
||||||
|
}
|
||||||
|
|
||||||
|
const createdActivity = await activityService.create(activityDto as ActivityDto)
|
||||||
|
|
||||||
|
// ActivityItem oluştur
|
||||||
|
const activityItemDto: Partial<ActivityItemDto> = {
|
||||||
|
activityId: createdActivity.id,
|
||||||
type: 'note',
|
type: 'note',
|
||||||
entityName,
|
entityName,
|
||||||
entityId,
|
entityId,
|
||||||
subject,
|
subject: subject || 'Not',
|
||||||
content: content || (files.length > 0 ? `${files.length} dosya eklendi` : ''),
|
content: content || (files.length > 0 ? `${files.length} dosya eklendi` : ''),
|
||||||
creatorId: user.id,
|
|
||||||
creationTime: timestamp,
|
|
||||||
attachedFiles: [], // Dosyaları buraya ekleyeceğiz
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dosyaları yükle ve note'a attach et
|
const createdActivityItem = await activityService.createItem(activityItemDto as ActivityItemDto)
|
||||||
|
|
||||||
|
// Dosyaları yükle
|
||||||
const uploadedFiles: ActivityFile[] = []
|
const uploadedFiles: ActivityFile[] = []
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
try {
|
try {
|
||||||
const uploadedFile = await new Promise<ActivityFile>((resolve, reject) => {
|
const activityFileDto: Partial<ActivityFileDto> = {
|
||||||
const reader = new FileReader()
|
activityItemId: createdActivityItem.id,
|
||||||
reader.onload = () => {
|
|
||||||
const newFile: ActivityFile = {
|
|
||||||
id: `${baseId}_file_${Math.random().toString(36).substr(2, 9)}`,
|
|
||||||
entityName,
|
entityName,
|
||||||
entityId,
|
entityId,
|
||||||
fileName: file.name,
|
fileName: file.name,
|
||||||
fileSize: file.size,
|
fileSize: file.size,
|
||||||
fileType: file.type,
|
fileType: file.type,
|
||||||
filePath: `uploads/${entityName}/${entityId}/${file.name}`,
|
filePath: `uploads/${entityName}/${entityId}/${file.name}`,
|
||||||
creatorId: user.id,
|
|
||||||
creationTime: timestamp,
|
|
||||||
}
|
}
|
||||||
resolve(newFile)
|
|
||||||
|
const createdFile = await activityService.uploadFile(activityFileDto as ActivityFileDto)
|
||||||
|
|
||||||
|
const newFile: ActivityFile = {
|
||||||
|
id: createdFile.id,
|
||||||
|
entityName: createdFile.entityName || entityName,
|
||||||
|
entityId: createdFile.entityId || entityId,
|
||||||
|
fileName: createdFile.fileName || file.name,
|
||||||
|
fileSize: createdFile.fileSize || file.size,
|
||||||
|
fileType: createdFile.fileType || file.type,
|
||||||
|
filePath: createdFile.filePath || '',
|
||||||
|
creatorId: createdFile.creatorId || user.id,
|
||||||
|
creationTime: createdFile.creationTime ? new Date(createdFile.creationTime) : new Date(),
|
||||||
}
|
}
|
||||||
reader.onerror = () => reject(reader.error)
|
|
||||||
reader.readAsDataURL(file)
|
uploadedFiles.push(newFile)
|
||||||
})
|
|
||||||
uploadedFiles.push(uploadedFile)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('File upload failed:', error)
|
console.error('File upload failed:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note'a dosyaları ekle
|
// Yeni ActivityItem'ı local state'e ekle
|
||||||
newActivityItem.attachedFiles = uploadedFiles
|
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
|
||||||
|
}
|
||||||
|
|
||||||
// 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) {
|
if (uploadedFiles.length > 0) {
|
||||||
setFiles((prev) => [...prev, ...uploadedFiles])
|
setFiles((prev) => [...prev, ...uploadedFiles])
|
||||||
}
|
}
|
||||||
|
|
||||||
return newActivityItem
|
return newActivityItem
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to create note:', error)
|
||||||
|
throw error
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const addFile = (file: File) => {
|
|
||||||
return new Promise<ActivityFile>((resolve, reject) => {
|
|
||||||
// Simulate file upload - gerçek implementasyonda API call yapılacak
|
|
||||||
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)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const deleteActivity = (itemId: string) => {
|
|
||||||
|
|
||||||
|
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))
|
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) => {
|
||||||
|
try {
|
||||||
|
// API'dan ActivityFile'ı sil
|
||||||
|
await activityService.deleteFile(fileId)
|
||||||
|
|
||||||
|
// Local state'ten kaldır
|
||||||
setFiles((prev) => prev.filter((file) => file.id !== fileId))
|
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,
|
||||||
) => {
|
) => {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const newMessageItems: ActivityItem[] = []
|
||||||
|
|
||||||
// Her recipient için ayrı mesaj aktivitesi oluştur
|
// Her recipient için ayrı mesaj aktivitesi oluştur
|
||||||
const newMessageItems: ActivityItem[] = recipients.map((recipient) => ({
|
for (const recipient of recipients) {
|
||||||
id: `message_${Date.now()}_${Math.random().toString(36).substr(2, 9)}_${recipient.value}`,
|
try {
|
||||||
type: 'message' as const,
|
// Activity oluştur
|
||||||
|
const activityDto: Partial<ActivityDto> = {
|
||||||
|
type: 'message',
|
||||||
|
subject,
|
||||||
|
content,
|
||||||
|
recipientUserName: recipient.label,
|
||||||
|
}
|
||||||
|
|
||||||
|
const createdActivity = await activityService.create(activityDto as ActivityDto)
|
||||||
|
|
||||||
|
// ActivityItem oluştur
|
||||||
|
const activityItemDto: Partial<ActivityItemDto> = {
|
||||||
|
activityId: createdActivity.id,
|
||||||
|
type: 'message',
|
||||||
entityName,
|
entityName,
|
||||||
entityId,
|
entityId,
|
||||||
recipientUserId: recipient.value,
|
recipientUserId: recipient.value,
|
||||||
recipientUserName: recipient.label,
|
recipientUserName: recipient.label,
|
||||||
subject,
|
subject,
|
||||||
content,
|
content,
|
||||||
creatorId: user.id,
|
}
|
||||||
creationTime: new Date(),
|
|
||||||
}))
|
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
|
// Tüm mesajları activityItems'a ekle
|
||||||
setActivityItems((prev) => [...prev, ...newMessageItems])
|
setActivityItems((prev) => [...prev, ...newMessageItems])
|
||||||
return 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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue