akfatimeline 1.0.2 → 1.0.5
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 +3277 -1
- package/dist/dist/components/Timeline/DatePickerComponent.js +17 -0
- 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 +29 -0
- package/dist/dist/components/Timeline/MasterHeader.js +68 -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 +616 -0
- package/dist/dist/components/Timeline/Timeline.js +304 -0
- package/dist/dist/components/Timeline/TimelineCell.js +8 -0
- package/dist/dist/components/Timeline/TimelineContent.js +447 -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 +126 -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/dist/Timeline.js +3277 -0
- package/public/dist/dist/components/Timeline/DatePickerComponent.js +17 -0
- package/public/dist/dist/components/Timeline/DragAndDropHandler.js +35 -0
- package/public/dist/dist/components/Timeline/EventTooltip.js +206 -0
- package/public/dist/dist/components/Timeline/Indicator.js +29 -0
- package/public/dist/dist/components/Timeline/MasterHeader.js +68 -0
- package/public/dist/dist/components/Timeline/Resources.js +53 -0
- package/public/dist/dist/components/Timeline/ResourcesHeader.js +14 -0
- package/public/dist/dist/components/Timeline/Timeline.css +616 -0
- package/public/dist/dist/components/Timeline/Timeline.js +304 -0
- package/public/dist/dist/components/Timeline/TimelineCell.js +8 -0
- package/public/dist/dist/components/Timeline/TimelineContent.js +447 -0
- package/public/dist/dist/components/Timeline/TimelineEvents.js +114 -0
- package/public/dist/dist/components/Timeline/TimelineHeader.js +43 -0
- package/public/dist/dist/components/Timeline/TimelineMonthContainer.js +29 -0
- package/public/dist/dist/components/Timeline/TimelineResources.js +16 -0
- package/public/dist/dist/hooks/useDragAndDrop.js +80 -0
- package/public/dist/dist/hooks/useEventDragDrop.js +126 -0
- package/public/dist/dist/hooks/useExtendEvent.js +28 -0
- package/public/dist/dist/utils/HorizontalVirtualScroll.js +0 -0
- package/public/dist/dist/utils/dateUtils.js +36 -0
- package/public/dist/dist/utils/filterTimelineData.js +21 -0
- package/public/dist/dist/utils/timelineUtils.js +40 -0
- 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
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { useRef, useEffect } from "react";
|
|
2
|
+
import flatpickr from "flatpickr";
|
|
3
|
+
import "flatpickr/dist/themes/material_green.css"; // Tema
|
|
4
|
+
|
|
5
|
+
const DatePickerComponent = ({ onDateSelect }) => {
|
|
6
|
+
const pickerRef = useRef();
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
flatpickr(pickerRef.current, {
|
|
10
|
+
onChange: ([selectedDate]) => onDateSelect(selectedDate),
|
|
11
|
+
});
|
|
12
|
+
}, []);
|
|
13
|
+
|
|
14
|
+
return <input type="text" ref={pickerRef} />;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default DatePickerComponent;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "dd/mm/yyyy" formatındaki bir tarih string'ini Date objesine dönüştürür.
|
|
3
|
+
* Eğer dateInput bir string değilse, direkt Date objesini döndürür.
|
|
4
|
+
* @param {string | Object | Date} dateInput - "dd/mm/yyyy" formatında tarih stringi veya {fullDate: Date, display: string} objesi veya Date objesi.
|
|
5
|
+
* @returns {Date} - Date objesi.
|
|
6
|
+
*/
|
|
7
|
+
export const parseDate = (dateInput) => {
|
|
8
|
+
if (dateInput instanceof Date) {
|
|
9
|
+
return dateInput;
|
|
10
|
+
}
|
|
11
|
+
if (typeof dateInput === 'string') {
|
|
12
|
+
const [day, month, year] = dateInput.split("/").map(Number);
|
|
13
|
+
return new Date(year, month - 1, day);
|
|
14
|
+
} else if (typeof dateInput === 'object' && dateInput.fullDate instanceof Date) {
|
|
15
|
+
return new Date(dateInput.fullDate);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
console.error("parseDate received invalid input:", dateInput);
|
|
19
|
+
return new Date(); // veya hata fırlat
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Bir tarihin belirli bir aralık içinde olup olmadığını kontrol eder.
|
|
25
|
+
* @param {string | Object | Date} date - "dd/mm/yyyy" formatında tarih stringi, {fullDate: Date, display: string} objesi veya Date objesi.
|
|
26
|
+
* @param {string | Object | Date} startDate - "dd/mm/yyyy" formatında başlangıç tarihi stringi, {fullDate: Date, display: string} objesi veya Date objesi.
|
|
27
|
+
* @param {string | Object | Date} endDate - "dd/mm/yyyy" formatında bitiş tarihi stringi, {fullDate: Date, display: string} objesi veya Date objesi.
|
|
28
|
+
* @returns {boolean} - Tarih aralık içinde ise true, değilse false.
|
|
29
|
+
*/
|
|
30
|
+
export const isDateInRange = (date, startDate, endDate) => {
|
|
31
|
+
const d = parseDate(date);
|
|
32
|
+
const start = parseDate(startDate);
|
|
33
|
+
const end = parseDate(endDate);
|
|
34
|
+
return d >= start && d <= end;
|
|
35
|
+
};
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// src/components/Timeline/EventTooltip.js
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
const EventTooltip = ({ event, position = { top: 0, left: 0 }, onClose, onEdit, onDelete }) => {
|
|
5
|
+
if (!event) return null;
|
|
6
|
+
|
|
7
|
+
const { top, left } = position;
|
|
8
|
+
|
|
9
|
+
// Rezervasyon durumuna göre renk belirleme
|
|
10
|
+
const getStatusColor = (status) => {
|
|
11
|
+
switch (status) {
|
|
12
|
+
case "Confirmed":
|
|
13
|
+
return "#4caf50"; // Yeşil
|
|
14
|
+
case "Pending":
|
|
15
|
+
return "#ff9800"; // Turuncu
|
|
16
|
+
case "Cancelled":
|
|
17
|
+
return "#f44336"; // Kırmızı
|
|
18
|
+
case "Completed":
|
|
19
|
+
return "#2196f3"; // Mavi
|
|
20
|
+
default:
|
|
21
|
+
return "#9e9e9e"; // Gri
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const statusColor = getStatusColor(event.status);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
style={{
|
|
30
|
+
position: "absolute",
|
|
31
|
+
top: top - 200, // Tooltip'in biraz yukarıda görünmesi için
|
|
32
|
+
left: left + 70,
|
|
33
|
+
transform: "translateX(-50%)",
|
|
34
|
+
backgroundColor: "#ffffff",
|
|
35
|
+
color: "#333333",
|
|
36
|
+
borderRadius: "10px",
|
|
37
|
+
boxShadow: "0 8px 16px rgba(0, 0, 0, 0.2)",
|
|
38
|
+
fontSize: "16px",
|
|
39
|
+
zIndex: 1000,
|
|
40
|
+
pointerEvents: "auto", // Tooltip'in tıklanabilir olmasını sağlar
|
|
41
|
+
whiteSpace: "normal",
|
|
42
|
+
maxWidth: "400px",
|
|
43
|
+
width: "100%",
|
|
44
|
+
transition: "opacity 0.3s ease, transform 0.3s ease",
|
|
45
|
+
}}
|
|
46
|
+
>
|
|
47
|
+
{/* Kapatma Butonu */}
|
|
48
|
+
{onClose && (
|
|
49
|
+
<button
|
|
50
|
+
onClick={onClose}
|
|
51
|
+
style={{
|
|
52
|
+
position: "absolute",
|
|
53
|
+
top: "10px",
|
|
54
|
+
right: "15px",
|
|
55
|
+
background: "transparent",
|
|
56
|
+
border: "none",
|
|
57
|
+
color: "#aaa",
|
|
58
|
+
fontSize: "24px",
|
|
59
|
+
cursor: "pointer",
|
|
60
|
+
transition: "color 0.2s",
|
|
61
|
+
}}
|
|
62
|
+
aria-label="Kapat"
|
|
63
|
+
onMouseOver={(e) => (e.target.style.color = "#000")}
|
|
64
|
+
onMouseOut={(e) => (e.target.style.color = "#aaa")}
|
|
65
|
+
>
|
|
66
|
+
×
|
|
67
|
+
</button>
|
|
68
|
+
)}
|
|
69
|
+
|
|
70
|
+
{/* Header */}
|
|
71
|
+
<div
|
|
72
|
+
style={{
|
|
73
|
+
backgroundColor: statusColor,
|
|
74
|
+
color: "#ffffff",
|
|
75
|
+
padding: "15px 20px",
|
|
76
|
+
borderTopLeftRadius: "10px",
|
|
77
|
+
borderTopRightRadius: "10px",
|
|
78
|
+
display: "flex",
|
|
79
|
+
flexDirection: "column",
|
|
80
|
+
gap: "5px",
|
|
81
|
+
}}
|
|
82
|
+
>
|
|
83
|
+
<div style={{ fontWeight: "bold", fontSize: "18px" }}>{event.title}</div>
|
|
84
|
+
<div style={{ fontSize: "14px" }}>Rezervasyon ID: {event.reservationId}</div>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
{/* İçerik */}
|
|
88
|
+
<div style={{ padding: "20px", display: "flex", flexDirection: "column", gap: "15px" }}>
|
|
89
|
+
{/* Misafirler */}
|
|
90
|
+
{Array.isArray(event.guestNames) && (
|
|
91
|
+
<div>
|
|
92
|
+
<strong>Misafirler:</strong> {event.guestNames.join(", ")}
|
|
93
|
+
</div>
|
|
94
|
+
)}
|
|
95
|
+
|
|
96
|
+
{/* Giriş ve Çıkış Tarihleri */}
|
|
97
|
+
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: "10px" }}>
|
|
98
|
+
<div>
|
|
99
|
+
<strong>Giriş:</strong> {new Date(event.startDate).toLocaleDateString()}
|
|
100
|
+
</div>
|
|
101
|
+
<div>
|
|
102
|
+
<strong>Çıkış:</strong> {new Date(event.endDate).toLocaleDateString()}
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
{/* Ödeme Bilgileri */}
|
|
107
|
+
{(event.totalAmount !== undefined || event.amountPaid !== undefined) && (
|
|
108
|
+
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: "10px" }}>
|
|
109
|
+
{event.amountPaid !== undefined && (
|
|
110
|
+
<div>
|
|
111
|
+
<strong>Ödenen Miktar:</strong> ${event.amountPaid.toFixed(2)}
|
|
112
|
+
</div>
|
|
113
|
+
)}
|
|
114
|
+
{event.totalAmount !== undefined && (
|
|
115
|
+
<div>
|
|
116
|
+
<strong>Toplam Borç:</strong> ${event.totalAmount.toFixed(2)}
|
|
117
|
+
</div>
|
|
118
|
+
)}
|
|
119
|
+
</div>
|
|
120
|
+
)}
|
|
121
|
+
|
|
122
|
+
{/* Rezervasyon Durumu */}
|
|
123
|
+
{event.status && (
|
|
124
|
+
<div>
|
|
125
|
+
<strong>Durum:</strong> {event.status}
|
|
126
|
+
</div>
|
|
127
|
+
)}
|
|
128
|
+
|
|
129
|
+
{/* Rezervasyon Notu */}
|
|
130
|
+
{event.note && (
|
|
131
|
+
<div>
|
|
132
|
+
<strong>Not:</strong> {event.note}
|
|
133
|
+
</div>
|
|
134
|
+
)}
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
{/* Footer */}
|
|
139
|
+
<div
|
|
140
|
+
style={{
|
|
141
|
+
padding: "15px 20px",
|
|
142
|
+
borderTop: "1px solid #ddd",
|
|
143
|
+
display: "flex",
|
|
144
|
+
justifyContent: "flex-end",
|
|
145
|
+
gap: "10px",
|
|
146
|
+
borderBottomLeftRadius: "10px",
|
|
147
|
+
borderBottomRightRadius: "10px",
|
|
148
|
+
}}
|
|
149
|
+
>
|
|
150
|
+
{/* Düzenle Butonu */}
|
|
151
|
+
{onEdit && (
|
|
152
|
+
<button
|
|
153
|
+
onClick={() => onEdit(event)}
|
|
154
|
+
style={{
|
|
155
|
+
padding: "8px 16px",
|
|
156
|
+
backgroundColor: "#2196f3",
|
|
157
|
+
color: "#ffffff",
|
|
158
|
+
border: "none",
|
|
159
|
+
borderRadius: "4px",
|
|
160
|
+
cursor: "pointer",
|
|
161
|
+
fontSize: "14px",
|
|
162
|
+
display: "flex",
|
|
163
|
+
alignItems: "center",
|
|
164
|
+
gap: "5px",
|
|
165
|
+
transition: "background-color 0.2s",
|
|
166
|
+
}}
|
|
167
|
+
onMouseOver={(e) => (e.target.style.backgroundColor = "#1976d2")}
|
|
168
|
+
onMouseOut={(e) => (e.target.style.backgroundColor = "#2196f3")}
|
|
169
|
+
>
|
|
170
|
+
{/* Düzenle İkonu */}
|
|
171
|
+
<span role="img" aria-label="Düzenle">✏️</span>
|
|
172
|
+
Düzenle
|
|
173
|
+
</button>
|
|
174
|
+
)}
|
|
175
|
+
|
|
176
|
+
{/* Sil Butonu */}
|
|
177
|
+
{onDelete && (
|
|
178
|
+
<button
|
|
179
|
+
onClick={() => onDelete(event.id)}
|
|
180
|
+
style={{
|
|
181
|
+
padding: "8px 16px",
|
|
182
|
+
backgroundColor: "#f44336",
|
|
183
|
+
color: "#ffffff",
|
|
184
|
+
border: "none",
|
|
185
|
+
borderRadius: "4px",
|
|
186
|
+
cursor: "pointer",
|
|
187
|
+
fontSize: "14px",
|
|
188
|
+
display: "flex",
|
|
189
|
+
alignItems: "center",
|
|
190
|
+
gap: "5px",
|
|
191
|
+
transition: "background-color 0.2s",
|
|
192
|
+
}}
|
|
193
|
+
onMouseOver={(e) => (e.target.style.backgroundColor = "#d32f2f")}
|
|
194
|
+
onMouseOut={(e) => (e.target.style.backgroundColor = "#f44336")}
|
|
195
|
+
>
|
|
196
|
+
{/* Sil İkonu */}
|
|
197
|
+
<span role="img" aria-label="Sil">🗑️</span>
|
|
198
|
+
Sil
|
|
199
|
+
</button>
|
|
200
|
+
)}
|
|
201
|
+
</div>
|
|
202
|
+
</div>
|
|
203
|
+
);
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
export default EventTooltip;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
const Indicator = ({ todayIndex, totalDays }) => {
|
|
4
|
+
if (todayIndex < 0 || todayIndex >= totalDays) {
|
|
5
|
+
console.log("Indicator not visible: Out of bounds");
|
|
6
|
+
return null; // Bugün timeline dışında ise çizgiyi gösterme
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<div
|
|
13
|
+
style={{
|
|
14
|
+
position: "absolute",
|
|
15
|
+
top: 0,
|
|
16
|
+
left: `calc(${(todayIndex + 0.5) / totalDays} * 100%)`, // Günün ortasına yerleştirmek için +0.5
|
|
17
|
+
width: "2px",
|
|
18
|
+
height: "100%",
|
|
19
|
+
backgroundColor: "transparent",
|
|
20
|
+
zIndex: 5,
|
|
21
|
+
borderStyle: "dashed", // Kesikli çizgi için
|
|
22
|
+
borderWidth: "0 0 0 2px", // Sadece sol tarafa kesikli çizgi
|
|
23
|
+
borderColor: "red",
|
|
24
|
+
}}
|
|
25
|
+
></div>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default Indicator;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import "./Timeline.css"; // veya MasterHeader.css, eğer ayrı dosyaya koyacaksan
|
|
3
|
+
import "flatpickr/dist/themes/material_green.css"; // Flatpickr Tema
|
|
4
|
+
|
|
5
|
+
const MasterHeader = ({
|
|
6
|
+
selectedDate,
|
|
7
|
+
onDateSelect,
|
|
8
|
+
onToday,
|
|
9
|
+
onAdvance,
|
|
10
|
+
onRetreat,
|
|
11
|
+
onMonthAdvance,
|
|
12
|
+
onMonthRetreat,
|
|
13
|
+
dayRange,
|
|
14
|
+
setDayRange,
|
|
15
|
+
}) => {
|
|
16
|
+
const formattedDate = new Date(
|
|
17
|
+
selectedDate.getTime() + 24 * 60 * 60 * 1000 - selectedDate.getTimezoneOffset() * 60000
|
|
18
|
+
)
|
|
19
|
+
.toISOString()
|
|
20
|
+
.split("T")[0]; // YYYY-MM-DD formatı
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div className="master-header-container">
|
|
24
|
+
<div className="master-header-buttons">
|
|
25
|
+
<button className="master-header-btn" onClick={onMonthRetreat}>
|
|
26
|
+
1 Ay Geri
|
|
27
|
+
</button>
|
|
28
|
+
|
|
29
|
+
<button className="master-header-btn" onClick={onRetreat}>
|
|
30
|
+
5 Gün Geri
|
|
31
|
+
</button>
|
|
32
|
+
|
|
33
|
+
<input
|
|
34
|
+
type="date"
|
|
35
|
+
className="master-header-date-picker"
|
|
36
|
+
value={formattedDate} // Seçili tarih burada gösteriliyor
|
|
37
|
+
onChange={(e) => onDateSelect(e.target.value)} // Tarih seçimi
|
|
38
|
+
onKeyDown={(e) => e.preventDefault()} // Manuel girişleri engelle
|
|
39
|
+
/>
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
<button className="master-header-btn" onClick={onAdvance}>
|
|
43
|
+
5 Gün İleri
|
|
44
|
+
</button>
|
|
45
|
+
|
|
46
|
+
<button className="master-header-btn" onClick={onMonthAdvance}>
|
|
47
|
+
1 Ay İleri
|
|
48
|
+
</button>
|
|
49
|
+
|
|
50
|
+
<button className="master-header-btn" onClick={onToday}>
|
|
51
|
+
Bugün
|
|
52
|
+
</button>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<select
|
|
56
|
+
className="master-header-select"
|
|
57
|
+
value={dayRange}
|
|
58
|
+
onChange={(e) => setDayRange(parseInt(e.target.value, 10))}
|
|
59
|
+
>
|
|
60
|
+
<option value={30}>30 Gün</option>
|
|
61
|
+
<option value={60}>60 Gün</option>
|
|
62
|
+
<option value={90}>90 Gün</option>
|
|
63
|
+
</select>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default MasterHeader;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
const Resources = ({
|
|
4
|
+
groupedResources = [], // Kaynakların listesi
|
|
5
|
+
collapsedGroups = {}, // Grupların açık/kapalı durumunu tutan nesne
|
|
6
|
+
toggleGroupCollapse, // Grupları açma/kapama fonksiyonu
|
|
7
|
+
resourceSettings = {
|
|
8
|
+
showIdAsName: false, // Varsayılan: `name` varsa onu göster, yoksa `id`
|
|
9
|
+
isGrouped: true, // Varsayılan: Gruplama açık
|
|
10
|
+
isCollapsible: true, // Varsayılan: Gruplar açılıp kapanabilir
|
|
11
|
+
},
|
|
12
|
+
}) => {
|
|
13
|
+
const { showIdAsName, isGrouped, isCollapsible } = resourceSettings;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div className="timeline-resources">
|
|
17
|
+
{isGrouped ? (
|
|
18
|
+
// Gruplama aktif
|
|
19
|
+
groupedResources.map((group, groupIndex) => (
|
|
20
|
+
<div key={groupIndex} className="resource-group">
|
|
21
|
+
{/* Grup Başlığı */}
|
|
22
|
+
<div
|
|
23
|
+
className="resource-group-header"
|
|
24
|
+
onClick={() => isCollapsible && toggleGroupCollapse(group.groupName)}
|
|
25
|
+
>
|
|
26
|
+
{group.groupName}{" "}
|
|
27
|
+
{isCollapsible && (collapsedGroups[group.groupName] ? "▲" : "▼")}
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
{/* Grup İçindeki Kaynaklar */}
|
|
31
|
+
{!collapsedGroups[group.groupName] &&
|
|
32
|
+
group.resources.map((resource, resourceIndex) => (
|
|
33
|
+
<div key={resourceIndex} className="resource-cell">
|
|
34
|
+
{showIdAsName ? resource.id : resource.name || resource.id}
|
|
35
|
+
{/* Eğer `name` yoksa `id` kullanılır */}
|
|
36
|
+
</div>
|
|
37
|
+
))}
|
|
38
|
+
</div>
|
|
39
|
+
))
|
|
40
|
+
) : (
|
|
41
|
+
// Gruplama yok
|
|
42
|
+
groupedResources.flatMap((group) => group.resources).map((resource, resourceIndex) => (
|
|
43
|
+
<div key={resourceIndex} className="resource-cell">
|
|
44
|
+
{showIdAsName ? resource.id : resource.name || resource.id}
|
|
45
|
+
{/* Eğer `name` yoksa `id` kullanılır */}
|
|
46
|
+
</div>
|
|
47
|
+
))
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default Resources;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// ResourcesHeader.js
|
|
2
|
+
import React from "react";
|
|
3
|
+
import "./Timeline.css";
|
|
4
|
+
|
|
5
|
+
const ResourcesHeader = ({ content }) => {
|
|
6
|
+
return (
|
|
7
|
+
<div className="resources-header">
|
|
8
|
+
{/* content => string veya React node */}
|
|
9
|
+
{content}
|
|
10
|
+
</div>
|
|
11
|
+
);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default ResourcesHeader;
|