akfatimeline 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +5 -3
- package/CHANGELOG.md +35 -0
- package/dist/Timeline.js +2292 -1
- package/dist/dist/components/Timeline/DragAndDropHandler.js +35 -0
- package/dist/dist/components/Timeline/EventTooltip.js +206 -0
- package/dist/dist/components/Timeline/Indicator.js +30 -0
- package/dist/dist/components/Timeline/MasterHeader.js +55 -0
- package/dist/dist/components/Timeline/Resources.js +53 -0
- package/dist/dist/components/Timeline/ResourcesHeader.js +14 -0
- package/dist/dist/components/Timeline/Timeline.css +534 -0
- package/dist/dist/components/Timeline/Timeline.js +277 -0
- package/dist/dist/components/Timeline/TimelineCell.js +8 -0
- package/dist/dist/components/Timeline/TimelineContent.js +422 -0
- package/dist/dist/components/Timeline/TimelineEvents.js +114 -0
- package/dist/dist/components/Timeline/TimelineHeader.js +43 -0
- package/dist/dist/components/Timeline/TimelineMonthContainer.js +29 -0
- package/dist/dist/components/Timeline/TimelineResources.js +16 -0
- package/dist/dist/hooks/useDragAndDrop.js +80 -0
- package/dist/dist/hooks/useEventDragDrop.js +120 -0
- package/dist/dist/hooks/useExtendEvent.js +28 -0
- package/dist/dist/utils/HorizontalVirtualScroll.js +0 -0
- package/dist/dist/utils/dateUtils.js +36 -0
- package/dist/dist/utils/filterTimelineData.js +21 -0
- package/dist/dist/utils/timelineUtils.js +40 -0
- package/package.json +2 -1
- package/public/index kutuphane /304/261c/304/261n.html" +43 -0
- package/public/index tasarim icin.html +20 -0
- package/src/App.js +161 -154
- package/src/components/Timeline/DatePickerComponent.js +17 -0
- package/src/components/Timeline/EventTooltip.js +1 -1
- package/src/components/Timeline/Indicator.js +1 -2
- package/src/components/Timeline/MasterHeader.js +36 -23
- package/src/components/Timeline/Timeline.css +90 -8
- package/src/components/Timeline/Timeline.js +71 -44
- package/src/components/Timeline/TimelineContent.js +154 -129
- package/src/hooks/useEventDragDrop.js +22 -16
- package/webpack.config.js +25 -7
- package/src/App copy.js +0 -185
- package/src/components/Timeline/TimelineContent copy.js +0 -421
package/webpack.config.js
CHANGED
|
@@ -1,31 +1,49 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
|
+
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
|
2
3
|
|
|
3
4
|
module.exports = {
|
|
4
|
-
|
|
5
|
+
mode: "production", // Üretim modu
|
|
6
|
+
entry: "./src/components/Timeline/Timeline.js", // Ana giriş dosyası
|
|
5
7
|
output: {
|
|
6
|
-
path: path.resolve(__dirname, "dist"), // Çıkış
|
|
7
|
-
filename: "Timeline.js", //
|
|
8
|
-
library: "AkfaTimeline", //
|
|
8
|
+
path: path.resolve(__dirname, "dist"), // Çıkış klasörü
|
|
9
|
+
filename: "Timeline.js", // Ana çıkış dosyası
|
|
10
|
+
library: "AkfaTimeline", // Kütüphane adı
|
|
9
11
|
libraryTarget: "umd", // Evrensel modül formatı
|
|
10
12
|
globalObject: "this",
|
|
11
13
|
},
|
|
14
|
+
resolve: {
|
|
15
|
+
extensions: [".js", ".jsx"], // Çözülebilecek dosya türleri
|
|
16
|
+
},
|
|
12
17
|
module: {
|
|
13
18
|
rules: [
|
|
14
19
|
{
|
|
15
|
-
test: /\.js$/,
|
|
20
|
+
test: /\.(js|jsx)$/, // JavaScript ve JSX dosyaları için
|
|
16
21
|
exclude: /node_modules/,
|
|
17
22
|
use: {
|
|
18
23
|
loader: "babel-loader",
|
|
19
24
|
},
|
|
20
25
|
},
|
|
21
26
|
{
|
|
22
|
-
test: /\.css$/,
|
|
27
|
+
test: /\.css$/, // CSS dosyaları için
|
|
23
28
|
use: ["style-loader", "css-loader"],
|
|
24
29
|
},
|
|
25
30
|
],
|
|
26
31
|
},
|
|
32
|
+
optimization: {
|
|
33
|
+
minimize: false, // Terser'i devre dışı bırakıyoruz
|
|
34
|
+
},
|
|
27
35
|
externals: {
|
|
28
|
-
react: "react",
|
|
36
|
+
react: "react", // React ve ReactDOM'u dışa bırak
|
|
29
37
|
"react-dom": "react-dom",
|
|
30
38
|
},
|
|
39
|
+
plugins: [
|
|
40
|
+
// Gerekli dosyaları dist klasörüne kopyala
|
|
41
|
+
new CopyWebpackPlugin({
|
|
42
|
+
patterns: [
|
|
43
|
+
{ from: "src/components/Timeline", to: "dist/components/Timeline" },
|
|
44
|
+
{ from: "src/hooks", to: "dist/hooks" },
|
|
45
|
+
{ from: "src/utils", to: "dist/utils" },
|
|
46
|
+
],
|
|
47
|
+
}),
|
|
48
|
+
],
|
|
31
49
|
};
|
package/src/App copy.js
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import Timeline from "./components/Timeline/Timeline";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const App = () => {
|
|
6
|
-
const programDate = "2025-01-02";
|
|
7
|
-
const [dropInfo, setDropInfo] = useState(null);
|
|
8
|
-
|
|
9
|
-
const events = [
|
|
10
|
-
{
|
|
11
|
-
id: "lux-101-1",
|
|
12
|
-
title: "Room 101 Event",
|
|
13
|
-
startDate: new Date("2025-01-01"), // Giriş tarihi
|
|
14
|
-
endDate: new Date("2025-01-08"), // Çıkış tarihi
|
|
15
|
-
resourceId: "lux-101", // Kaynak ID
|
|
16
|
-
color: "#ff5733", // Renk
|
|
17
|
-
totalAmount: 500, // Toplam borç
|
|
18
|
-
amountPaid: 200, // Ödenen miktar
|
|
19
|
-
status: "Confirmed", // Rezervasyon durumu
|
|
20
|
-
note: "Misafirler özel talep olarak ekstra yastık istediler." // Rezervasyon notu
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
id: "lux-102-1",
|
|
24
|
-
title: "Room 102 Event",
|
|
25
|
-
startDate: new Date("2025-01-02"),
|
|
26
|
-
endDate: new Date("2025-01-04"),
|
|
27
|
-
resourceId: "lux-102",
|
|
28
|
-
color: "#33a1ff",
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
id: "lux-103-1",
|
|
32
|
-
title: "Room 103 Event",
|
|
33
|
-
startDate: new Date("2025-01-01"),
|
|
34
|
-
endDate: new Date("2025-01-02"),
|
|
35
|
-
resourceId: "lux-103",
|
|
36
|
-
color: "#33ff57",
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
id: "fam-201-1",
|
|
40
|
-
title: "Suite 201 Event",
|
|
41
|
-
startDate: new Date("2025-01-01"),
|
|
42
|
-
endDate: new Date("2025-01-02"),
|
|
43
|
-
resourceId: "fam-201",
|
|
44
|
-
color: "#ff33a1",
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
id: "fam-202-1",
|
|
48
|
-
title: "Suite 202 Event",
|
|
49
|
-
startDate: new Date("2025-01-03"),
|
|
50
|
-
endDate: new Date("2025-01-05"),
|
|
51
|
-
resourceId: "fam-202",
|
|
52
|
-
color: "#a1ff33",
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
id: "bus-301-1",
|
|
56
|
-
title: "Room 301 Event",
|
|
57
|
-
startDate: new Date("2025-01-02"),
|
|
58
|
-
endDate: new Date("2025-01-04"),
|
|
59
|
-
resourceId: "bus-301",
|
|
60
|
-
color: "#ff9a00",
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
id: "vip-401-1",
|
|
64
|
-
title: "VIP 401 Event",
|
|
65
|
-
startDate: new Date("2025-01-04"),
|
|
66
|
-
endDate: new Date("2025-01-06"),
|
|
67
|
-
resourceId: "vip-401",
|
|
68
|
-
color: "#800080",
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
id: "vip-402-1",
|
|
72
|
-
title: "VIP 402 Event",
|
|
73
|
-
startDate: new Date("2025-01-05"),
|
|
74
|
-
endDate: new Date("2025-01-06"),
|
|
75
|
-
resourceId: "vip-402",
|
|
76
|
-
color: "#008080",
|
|
77
|
-
},
|
|
78
|
-
];
|
|
79
|
-
|
|
80
|
-
const resources = [
|
|
81
|
-
{
|
|
82
|
-
groupName: "Luxury Rooms",
|
|
83
|
-
resources: [
|
|
84
|
-
{ id: "lux-101", name: "Room 101" },
|
|
85
|
-
{ id: "lux-102", name: "Room 102" },
|
|
86
|
-
{ id: "lux-103", name: "Room 103" },
|
|
87
|
-
{ id: "lux-104", name: "Room 104" },
|
|
88
|
-
],
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
groupName: "Family Suites",
|
|
92
|
-
resources: [
|
|
93
|
-
{ id: "fam-201", name: "Suite 201" },
|
|
94
|
-
{ id: "fam-202", name: "Suite 202" },
|
|
95
|
-
{ id: "fam-203", name: "Suite 203" },
|
|
96
|
-
{ id: "fam-204", name: "Suite 204" },
|
|
97
|
-
],
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
groupName: "Business Class",
|
|
101
|
-
resources: [
|
|
102
|
-
{ id: "bus-301", name: "Room 301" },
|
|
103
|
-
{ id: "bus-302", name: "Room 302" },
|
|
104
|
-
{ id: "bus-303", name: "Room 303" },
|
|
105
|
-
{ id: "bus-304", name: "Room 304" },
|
|
106
|
-
],
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
groupName: "VIP Exclusive",
|
|
110
|
-
resources: [
|
|
111
|
-
{ id: "vip-401", name: "VIP 401" },
|
|
112
|
-
{ id: "vip-402", name: "VIP 402" },
|
|
113
|
-
{ id: "vip-403", name: "VIP 403" },
|
|
114
|
-
{ id: "vip-404", name: "VIP 404" },
|
|
115
|
-
|
|
116
|
-
],
|
|
117
|
-
},
|
|
118
|
-
];
|
|
119
|
-
|
|
120
|
-
const resourceSettings = {
|
|
121
|
-
showIdAsName: false,
|
|
122
|
-
isGrouped: true,
|
|
123
|
-
isCollapsible: true,
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// Yeni prop'lar (boolean veya callback) örnekleri:
|
|
127
|
-
const eventsDragOn = true; // Etkinlikleri sürükle-bırak aktif mi?
|
|
128
|
-
const eventsExtendOn = true; // Etkinliği sağ kenarından uzatma aktif mi?
|
|
129
|
-
const createNewEventOn = true; // Yeni event oluşturma aktif mi?
|
|
130
|
-
// Callback örnekleri:
|
|
131
|
-
const handleDragInfo = (dragData) => {
|
|
132
|
-
console.log("Dragged Event Info:", dragData);
|
|
133
|
-
// Kullanıcı bu veriyi yakalayıp kendi API'sine kaydedebilir
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
const [masterHeaderView, setMasterHeaderView] = useState(true);
|
|
137
|
-
const [resourceHeaderContent, setResourceHeaderContent] = useState("Akfa Timeline");
|
|
138
|
-
|
|
139
|
-
const handleExtendInfo = (extendData) => {
|
|
140
|
-
console.log("Extended Event Info:", extendData);
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const handleCreateEventInfo = (newEventData) => {
|
|
144
|
-
console.log("New Event Created:", newEventData);
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
const handleEventClick = (evt, ev) => {
|
|
148
|
-
console.log("Event clicked:", evt);
|
|
149
|
-
// evt: event objesi, ev: orijinal mouse event
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
const handleEventRightClick = (evt, ev) => {
|
|
153
|
-
ev.preventDefault(); // Sağ tık menüsü kapatmak istersen
|
|
154
|
-
console.log("Event right-clicked:", evt);
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
return (
|
|
158
|
-
<Timeline
|
|
159
|
-
resources={resources}
|
|
160
|
-
resourceSettings={resourceSettings}
|
|
161
|
-
programDate={programDate}
|
|
162
|
-
externalEvents={events}
|
|
163
|
-
indicatorOn={true}
|
|
164
|
-
events={events}
|
|
165
|
-
setDropInfo={setDropInfo}
|
|
166
|
-
|
|
167
|
-
eventsDragOn={eventsDragOn}
|
|
168
|
-
eventsExtendOn={eventsExtendOn}
|
|
169
|
-
createNewEventOn={createNewEventOn}
|
|
170
|
-
|
|
171
|
-
onDragInfo={handleDragInfo}
|
|
172
|
-
onExtendInfo={handleExtendInfo}
|
|
173
|
-
onCreateEventInfo={handleCreateEventInfo}
|
|
174
|
-
onEventClick={handleEventClick}
|
|
175
|
-
onEventRightClick={handleEventRightClick}
|
|
176
|
-
|
|
177
|
-
horizontalScrollOn={true} // => Yatay kaydırma aktifleştirilir
|
|
178
|
-
|
|
179
|
-
masterHeaderView={masterHeaderView}
|
|
180
|
-
resourceHeaderContent={resourceHeaderContent}
|
|
181
|
-
/>
|
|
182
|
-
);
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
export default App;
|
|
@@ -1,421 +0,0 @@
|
|
|
1
|
-
import React, { useState, useRef, useEffect } from "react";
|
|
2
|
-
import { parseDate } from "../../utils/dateUtils";
|
|
3
|
-
import useDragAndDrop from "../../hooks/useDragAndDrop";
|
|
4
|
-
import useEventDragDrop from "../../hooks/useEventDragDrop";
|
|
5
|
-
import EventTooltip from "./EventTooltip";
|
|
6
|
-
import Indicator from "./Indicator";
|
|
7
|
-
|
|
8
|
-
const TimelineContent = ({ groupedResources, dates, collapsedGroups, events, setEvents, onEventClick, todayIndex, indicatorOn, resourceSettings,
|
|
9
|
-
|
|
10
|
-
}) => {
|
|
11
|
-
|
|
12
|
-
const containerRef = useRef(null);
|
|
13
|
-
const { isDragging, dragStart, dragEnd } = useDragAndDrop(events, setEvents);
|
|
14
|
-
const totalDays = dates.length; // Toplam gün sayısı hesaplandı
|
|
15
|
-
const { handleDragStart, handleDragOver, handleDrop, handleDragEnd } = useEventDragDrop(events, setEvents);
|
|
16
|
-
|
|
17
|
-
console.log("events content:", events);
|
|
18
|
-
console.log("Event Resource ID:", events.resourceId);
|
|
19
|
-
console.log("Current Resource ID:", groupedResources);
|
|
20
|
-
|
|
21
|
-
// Tooltip için state
|
|
22
|
-
const [selectedEvent, setSelectedEvent] = useState(null);
|
|
23
|
-
const [tooltipPosition, setTooltipPosition] = useState({ top: 0, left: 0 });
|
|
24
|
-
// Yeni Event oluşturma durumu ve geçici event
|
|
25
|
-
const [isCreating, setIsCreating] = useState(false);
|
|
26
|
-
const [tempEvent, setTempEvent] = useState(null);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const handleEventClick = (event, e) => {
|
|
30
|
-
e.stopPropagation();
|
|
31
|
-
const eventElement = e.currentTarget;
|
|
32
|
-
if (eventElement) {
|
|
33
|
-
const rect = eventElement.getBoundingClientRect();
|
|
34
|
-
setTooltipPosition({
|
|
35
|
-
top: rect.top + window.scrollY,
|
|
36
|
-
left: rect.left + rect.width / 2 + window.scrollX,
|
|
37
|
-
});
|
|
38
|
-
setSelectedEvent(event); // Seçilen event'i state'e kaydediyoruz
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// Mouse hareketiyle geçici event'in bitiş tarihini güncelle
|
|
44
|
-
const handleMouseMove = (e) => {
|
|
45
|
-
if (isCreating && tempEvent) {
|
|
46
|
-
const cell = document.elementFromPoint(e.clientX, e.clientY);
|
|
47
|
-
|
|
48
|
-
// Hücre genişliğini dinamik olarak hesapla
|
|
49
|
-
const cellWidth = cell?.offsetWidth || 30;
|
|
50
|
-
|
|
51
|
-
const startX = tempEvent.startX || e.clientX; // İlk tıklamanın X pozisyonu
|
|
52
|
-
const deltaX = e.clientX - startX; // Hareket edilen mesafe
|
|
53
|
-
const daysToAdd = Math.max(1, Math.floor(deltaX / cellWidth)); // Gün hesaplama (en az 1 gün)
|
|
54
|
-
|
|
55
|
-
// EndDate'i güncelle
|
|
56
|
-
const newEndDate = new Date(tempEvent.startDate.getTime());
|
|
57
|
-
newEndDate.setDate(newEndDate.getDate() + daysToAdd);
|
|
58
|
-
|
|
59
|
-
// TempEvent'i güncelle ve yeni başlığı ayarla
|
|
60
|
-
setTempEvent({
|
|
61
|
-
...tempEvent,
|
|
62
|
-
endDate: newEndDate,
|
|
63
|
-
startX: startX,
|
|
64
|
-
title: `${daysToAdd} Gece`, // Gün sayısını ve "Gece" kelimesini başlığa ekle
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
console.log("Mouse X Delta:", deltaX);
|
|
68
|
-
console.log("Days to Add:", daysToAdd);
|
|
69
|
-
console.log("New End Date:", newEndDate);
|
|
70
|
-
console.log("Cell Width:", cellWidth);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// Mouse bırakıldığında geçici event'i kaydet
|
|
79
|
-
const handleMouseUp = () => {
|
|
80
|
-
if (isCreating && tempEvent) {
|
|
81
|
-
setEvents([...events, tempEvent]); // Geçici event kalıcı hale gelir
|
|
82
|
-
setTempEvent(null); // Geçici eventi sıfırla
|
|
83
|
-
setIsCreating(false); // Event oluşturmayı kapat
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// Yeni event oluşturma fonksiyonu
|
|
88
|
-
|
|
89
|
-
const handleCellClick = (resourceId, date) => {
|
|
90
|
-
const startDate = parseDate(date.fullDate);
|
|
91
|
-
const newEvent = {
|
|
92
|
-
id: Date.now(),
|
|
93
|
-
title: "1 Gece",
|
|
94
|
-
startDate,
|
|
95
|
-
endDate: new Date(startDate.getTime() + 24 * 60 * 60 * 1000),
|
|
96
|
-
resourceId,
|
|
97
|
-
color: "#ff5722",
|
|
98
|
-
};
|
|
99
|
-
setTempEvent(newEvent); // Geçici event state'e ekle
|
|
100
|
-
setIsCreating(true); // Yeni bir event oluşturuldu
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
// Event silme fonksiyonu
|
|
104
|
-
const handleDeleteEvent = (eventId) => {
|
|
105
|
-
setEvents(events.filter((event) => event.id !== eventId));
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
useEffect(() => {
|
|
110
|
-
if (isCreating) {
|
|
111
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
112
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
113
|
-
|
|
114
|
-
return () => {
|
|
115
|
-
window.removeEventListener("mousemove", handleMouseMove);
|
|
116
|
-
window.removeEventListener("mouseup", handleMouseUp);
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
}, );
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
// Sürükleme sırasında seçilen hücreleri vurgulamak için fonksiyon
|
|
123
|
-
const isCellSelected = (resourceId, date) => {
|
|
124
|
-
if (!dragStart || !dragEnd) return false;
|
|
125
|
-
if (resourceId !== dragStart.resourceId) return false;
|
|
126
|
-
|
|
127
|
-
const startIndex = dates.findIndex(
|
|
128
|
-
(d) => parseDate(d.fullDate).getTime() === parseDate(dragStart.date).getTime()
|
|
129
|
-
);
|
|
130
|
-
const endIndex = dates.findIndex(
|
|
131
|
-
(d) => parseDate(d.fullDate).getTime() === parseDate(dragEnd.date).getTime()
|
|
132
|
-
);
|
|
133
|
-
const currentIndex = dates.findIndex(
|
|
134
|
-
(d) => parseDate(d.fullDate).getTime() === parseDate(date.fullDate).getTime()
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
if (startIndex === -1 || endIndex === -1 || currentIndex === -1) return false;
|
|
138
|
-
|
|
139
|
-
return (
|
|
140
|
-
currentIndex >= Math.min(startIndex, endIndex) &&
|
|
141
|
-
currentIndex <= Math.max(startIndex, endIndex)
|
|
142
|
-
);
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const calculatePosition = (event, dates) => {
|
|
146
|
-
const startDate = parseDate(event.startDate);
|
|
147
|
-
const endDate = parseDate(event.endDate);
|
|
148
|
-
|
|
149
|
-
const startIndex = dates.findIndex(
|
|
150
|
-
(d) => parseDate(d.fullDate).toDateString() === startDate.toDateString()
|
|
151
|
-
);
|
|
152
|
-
const endIndex = dates.findIndex(
|
|
153
|
-
(d) => parseDate(d.fullDate).toDateString() === endDate.toDateString()
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
const totalDays = dates.length;
|
|
157
|
-
|
|
158
|
-
console.log("Total Days:", totalDays);
|
|
159
|
-
// Eğer başlangıç ve bitiş timeline'ın tamamen dışında ise, görünmez olarak işaretle
|
|
160
|
-
if (startIndex < 0 && endIndex < 0) {
|
|
161
|
-
// Eğer hem başlangıç hem de bitiş timeline'ın sol tarafında ise, tamamen görünmez
|
|
162
|
-
console.log("Event completely out of bounds on the left:", event.title);
|
|
163
|
-
return {
|
|
164
|
-
isVisible: false,
|
|
165
|
-
left: 0,
|
|
166
|
-
width: 0,
|
|
167
|
-
isPartialStart: false,
|
|
168
|
-
isPartialEnd: false,
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (startIndex >= totalDays && endIndex >= totalDays) {
|
|
173
|
-
// Eğer hem başlangıç hem de bitiş timeline'ın sağ tarafında ise, tamamen görünmez
|
|
174
|
-
console.log("Event completely out of bounds on the right:", event.title);
|
|
175
|
-
return {
|
|
176
|
-
isVisible: false,
|
|
177
|
-
left: 0,
|
|
178
|
-
width: 0,
|
|
179
|
-
isPartialStart: false,
|
|
180
|
-
isPartialEnd: false,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
// Etkin Başlangıç ve Bitiş İndeksleri
|
|
186
|
-
const effectiveStartIndex = Math.max(startIndex, 0); // Başlangıç en az 0 olmalı
|
|
187
|
-
const effectiveEndIndex = Math.min(endIndex, totalDays - 1); // Bitiş en fazla toplam gün sayısı - 1 olmalı
|
|
188
|
-
|
|
189
|
-
// Kesik başlangıç veya bitiş kontrolü
|
|
190
|
-
const isPartialStart = startIndex < 0; // Başlangıç timeline dışında mı?
|
|
191
|
-
const isPartialEnd = endIndex >= totalDays; // Bitiş timeline dışında mı?
|
|
192
|
-
|
|
193
|
-
// Sol tarafın ekran dışında kalması durumu
|
|
194
|
-
if (isPartialStart) {
|
|
195
|
-
console.log("Event partially visible on the left:", event.title);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Sağ tarafın ekran dışında kalması durumu
|
|
199
|
-
if (isPartialEnd) {
|
|
200
|
-
console.log("Event partially visible on the right:", event.title);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Başlangıç ve bitiş pozisyonlarını ayrı ayrı hesapla
|
|
204
|
-
const leftPercentage = ((effectiveStartIndex + (isPartialStart ? 0 : 0.5)) / totalDays) * 100;
|
|
205
|
-
const rightPercentage = ((effectiveEndIndex + (isPartialEnd ? 1 : 0.5)) / totalDays) * 100;
|
|
206
|
-
|
|
207
|
-
// Genişlik hesaplama
|
|
208
|
-
const widthPercentage = rightPercentage - leftPercentage;
|
|
209
|
-
|
|
210
|
-
// Sonuçları döndür
|
|
211
|
-
return {
|
|
212
|
-
isVisible: true,
|
|
213
|
-
left: `${leftPercentage}%`,
|
|
214
|
-
width: `${widthPercentage}%`,
|
|
215
|
-
isPartialStart,
|
|
216
|
-
isPartialEnd,
|
|
217
|
-
};
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
useEffect(() => {
|
|
228
|
-
if (isCreating) {
|
|
229
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
230
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
231
|
-
|
|
232
|
-
return () => {
|
|
233
|
-
window.removeEventListener("mousemove", handleMouseMove);
|
|
234
|
-
window.removeEventListener("mouseup", handleMouseUp);
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
}, );
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const handleCloseTooltip = () => {
|
|
243
|
-
setSelectedEvent(null);
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
const handleDelete = (eventId) => {
|
|
247
|
-
handleDeleteEvent(eventId);
|
|
248
|
-
handleCloseTooltip();
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
return (
|
|
252
|
-
<div
|
|
253
|
-
ref={containerRef}
|
|
254
|
-
style={{
|
|
255
|
-
display: "flex",
|
|
256
|
-
flexDirection: "column",
|
|
257
|
-
width: "100%",
|
|
258
|
-
userSelect: isDragging ? "none" : "auto",
|
|
259
|
-
position: "relative",
|
|
260
|
-
}}
|
|
261
|
-
>
|
|
262
|
-
|
|
263
|
-
{indicatorOn && <Indicator todayIndex={todayIndex} totalDays={totalDays} />}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
{groupedResources.map((group, groupIndex) => (
|
|
267
|
-
<div key={groupIndex} style={{ marginBottom: "0px" }}>
|
|
268
|
-
{/* Grup Başlığı */}
|
|
269
|
-
{resourceSettings.isGrouped && (
|
|
270
|
-
<div style={{ display: "flex", marginTop: "-0.08rem" }}>
|
|
271
|
-
{dates.map((dateObj, colIndex) => (
|
|
272
|
-
<div
|
|
273
|
-
key={`group-header-${groupIndex}-${colIndex}`}
|
|
274
|
-
style={{
|
|
275
|
-
flex: 1,
|
|
276
|
-
height: "2.58rem",
|
|
277
|
-
backgroundColor: "#4b5563",
|
|
278
|
-
border: "1px solid #ccc",
|
|
279
|
-
boxSizing: "border-box",
|
|
280
|
-
display: "flex",
|
|
281
|
-
alignItems: "center",
|
|
282
|
-
justifyContent: "center",
|
|
283
|
-
}}
|
|
284
|
-
></div>
|
|
285
|
-
))}
|
|
286
|
-
</div>
|
|
287
|
-
)}
|
|
288
|
-
|
|
289
|
-
{/* Kaynaklar */}
|
|
290
|
-
{!collapsedGroups[group.groupName] &&
|
|
291
|
-
group.resources.map((resource, rowIndex) => {
|
|
292
|
-
const resourceEvents = events.filter(
|
|
293
|
-
(event) => event.resourceId === resource.id
|
|
294
|
-
);
|
|
295
|
-
|
|
296
|
-
return (
|
|
297
|
-
<div
|
|
298
|
-
key={resource.id}
|
|
299
|
-
style={{
|
|
300
|
-
display: "flex",
|
|
301
|
-
boxSizing: "border-box",
|
|
302
|
-
position: "relative",
|
|
303
|
-
height: "40px",
|
|
304
|
-
border: "1px solid #ccc",
|
|
305
|
-
}}
|
|
306
|
-
>
|
|
307
|
-
{/* Event'leri Render Et */}
|
|
308
|
-
{resourceEvents.map((event) => {
|
|
309
|
-
const { isVisible, left, width, isPartialStart, isPartialEnd } =
|
|
310
|
-
calculatePosition(event, dates);
|
|
311
|
-
|
|
312
|
-
if (!isVisible) return null;
|
|
313
|
-
|
|
314
|
-
return (
|
|
315
|
-
<div
|
|
316
|
-
key={event.id}
|
|
317
|
-
draggable
|
|
318
|
-
onDragStart={(e) => handleDragStart(e, event.id)} // Sürükleme başlat
|
|
319
|
-
onDragEnd={() => handleDragEnd()} // Sürükleme bitir
|
|
320
|
-
onClick={(e) => handleEventClick(event, e)} // Tıklama olayını burada tetikliyoruz
|
|
321
|
-
style={{
|
|
322
|
-
position: "absolute",
|
|
323
|
-
top: "5px",
|
|
324
|
-
left: left,
|
|
325
|
-
width: width,
|
|
326
|
-
height: "80%",
|
|
327
|
-
backgroundColor: event.color || "#ff7f50",
|
|
328
|
-
color: "#fff",
|
|
329
|
-
fontSize: "14px",
|
|
330
|
-
padding: "5px",
|
|
331
|
-
borderTopLeftRadius: isPartialStart ? "0px" : "20px",
|
|
332
|
-
borderBottomLeftRadius: isPartialStart ? "0px" : "20px",
|
|
333
|
-
borderTopRightRadius: isPartialEnd ? "0px" : "20px",
|
|
334
|
-
borderBottomRightRadius: isPartialEnd ? "0px" : "20px",
|
|
335
|
-
textAlign: "left",
|
|
336
|
-
display: "flex",
|
|
337
|
-
alignItems: "center",
|
|
338
|
-
justifyContent: "center",
|
|
339
|
-
boxSizing: "border-box",
|
|
340
|
-
zIndex: 10,
|
|
341
|
-
overflow: "hidden",
|
|
342
|
-
textOverflow: "ellipsis",
|
|
343
|
-
whiteSpace: "nowrap",
|
|
344
|
-
border: "1px solid #fff",
|
|
345
|
-
cursor: "grab", // Sürükleme ikonu
|
|
346
|
-
}}
|
|
347
|
-
>
|
|
348
|
-
{event.title}
|
|
349
|
-
</div>
|
|
350
|
-
);
|
|
351
|
-
})}
|
|
352
|
-
|
|
353
|
-
{tempEvent && tempEvent.resourceId === resource.id && (
|
|
354
|
-
<div
|
|
355
|
-
style={{
|
|
356
|
-
position: "absolute",
|
|
357
|
-
...calculatePosition(tempEvent, dates),
|
|
358
|
-
top: "5px",
|
|
359
|
-
height: "80%",
|
|
360
|
-
backgroundColor: tempEvent.color,
|
|
361
|
-
opacity: 0.7,
|
|
362
|
-
borderRadius: "20px",
|
|
363
|
-
zIndex: 9,
|
|
364
|
-
display: "flex",
|
|
365
|
-
alignItems: "center",
|
|
366
|
-
justifyContent: "center",
|
|
367
|
-
color: "#fff",
|
|
368
|
-
fontSize: "14px",
|
|
369
|
-
}}
|
|
370
|
-
>
|
|
371
|
-
{tempEvent.title}
|
|
372
|
-
</div>
|
|
373
|
-
)}
|
|
374
|
-
|
|
375
|
-
{/* Tarih Hücreleri */}
|
|
376
|
-
{dates.map((dateObj, colIndex) => (
|
|
377
|
-
<div
|
|
378
|
-
key={`cell-${groupIndex}-${rowIndex}-${colIndex}`}
|
|
379
|
-
data-date={JSON.stringify(dateObj)}
|
|
380
|
-
data-resource-id={resource.id}
|
|
381
|
-
onMouseDown={() => handleCellClick(resource.id, dateObj)}
|
|
382
|
-
onDragOver={(e) => handleDragOver(e)} // Hücre üzerine sürükleme
|
|
383
|
-
onDrop={(e) =>
|
|
384
|
-
handleDrop(e, resource.id, parseDate(dateObj.fullDate)) // `dateObj.fullDate`'yi doğru şekilde geçiyoruz
|
|
385
|
-
} // Bırakma olayı
|
|
386
|
-
style={{
|
|
387
|
-
flex: 1,
|
|
388
|
-
height: "100%",
|
|
389
|
-
position: "relative",
|
|
390
|
-
borderLeft: colIndex === 0 ? "1px solid #ccc" : "none",
|
|
391
|
-
borderRight: "1px solid #ccc",
|
|
392
|
-
backgroundColor: isCellSelected(resource.id, dateObj)
|
|
393
|
-
? "rgba(59, 130, 246, 0.3)"
|
|
394
|
-
: "transparent",
|
|
395
|
-
cursor: "pointer",
|
|
396
|
-
}}
|
|
397
|
-
></div>
|
|
398
|
-
))}
|
|
399
|
-
</div>
|
|
400
|
-
);
|
|
401
|
-
})}
|
|
402
|
-
</div>
|
|
403
|
-
))}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
{selectedEvent && (
|
|
410
|
-
<EventTooltip
|
|
411
|
-
event={selectedEvent}
|
|
412
|
-
position={tooltipPosition}
|
|
413
|
-
onClose={handleCloseTooltip}
|
|
414
|
-
onDelete={() => handleDelete(selectedEvent.id)}
|
|
415
|
-
/>
|
|
416
|
-
)}
|
|
417
|
-
</div>
|
|
418
|
-
);
|
|
419
|
-
};
|
|
420
|
-
|
|
421
|
-
export default TimelineContent;
|