Skip to content

Commit f65a4b8

Browse files
authored
Merge pull request #35 from ubclaunchpad/borna_log_actions_menu
Log actions menu features implemented
2 parents 7443716 + 6cbef0b commit f65a4b8

File tree

1 file changed

+130
-31
lines changed

1 file changed

+130
-31
lines changed

frontend/src/pages/log_history/LogHistory.jsx

Lines changed: 130 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,34 @@ import ContentHeader from "../../components/ContentHeader/ContentHeader";
44
import LogTable from "../../components/LogHistory/LogTable";
55
import Pagination from "../../components/LogHistory/Pagination";
66
import {
7-
PencilSquareIcon,
7+
// PencilSquareIcon,
88
ArrowDownTrayIcon,
9-
AdjustmentsHorizontalIcon,
9+
// AdjustmentsHorizontalIcon,
1010
EyeIcon,
1111
TrashIcon,
1212
} from "@heroicons/react/24/outline";
1313
import "./LogHistory.css";
1414
import { useAuth } from "../../contexts/AuthContext";
1515
import { fetchData } from "../../utils/helpers/fetchData";
16-
17-
/** Array of log actions */
18-
const logActions = [
19-
{
20-
label: "Configure",
21-
icon: PencilSquareIcon,
22-
onClick: () => {},
23-
},
24-
{
25-
label: "Download",
26-
icon: ArrowDownTrayIcon,
27-
onClick: () => {},
28-
},
29-
{
30-
label: "Filter",
31-
icon: AdjustmentsHorizontalIcon,
32-
onClick: () => {},
33-
},
34-
{
35-
label: "View",
36-
icon: EyeIcon,
37-
onClick: () => {},
38-
},
39-
{
40-
label: "Delete",
41-
icon: TrashIcon,
42-
onClick: () => {},
43-
},
44-
];
16+
import supabase from "../../config/supabase";
17+
import { useNavigate } from "react-router-dom";
18+
19+
const convertToCSV = (data) => {
20+
if (!data || data.length === 0) return '';
21+
const headers = Object.keys(data[0]);
22+
const csvHeader = headers.join(',');
23+
const csvRows = data.map(row =>
24+
headers.map(header => {
25+
let cell = row[header] || '';
26+
// Handle cells that contain commas by wrapping in quotes
27+
if (cell.toString().includes(',')) {
28+
cell = `"${cell}"`;
29+
}
30+
return cell;
31+
}).join(',')
32+
);
33+
return [csvHeader, ...csvRows].join('\n');
34+
};
4535

4636
export default function LogHistory() {
4737
return (
@@ -54,6 +44,8 @@ export default function LogHistory() {
5444
}
5545

5646
function MainContent() {
47+
const navigate = useNavigate();
48+
5749
/** Retrieve user's logs from API */
5850
const [logs, setLogs] = useState([]);
5951
const { session } = useAuth();
@@ -114,6 +106,113 @@ function MainContent() {
114106
}));
115107
};
116108

109+
const handleDownloadLog = async (selectedLogs) => {
110+
try {
111+
112+
const selectedLogIds = Object.entries(selectedLogs)
113+
.filter(([, isSelected]) => isSelected)
114+
.map(([id]) => id);
115+
116+
if (selectedLogIds.length === 0) return;
117+
118+
const selectedLogData = logs.filter(log => selectedLogIds.includes(log.id));
119+
120+
const csvContent = convertToCSV(selectedLogData);
121+
122+
const blob = new Blob([csvContent], { type: 'text/csv' });
123+
const url = window.URL.createObjectURL(blob);
124+
const link = document.createElement('a');
125+
link.href = url;
126+
link.download = `selected_logs_${new Date().toISOString().split('T')[0]}.csv`;
127+
document.body.appendChild(link);
128+
link.click();
129+
document.body.removeChild(link);
130+
window.URL.revokeObjectURL(url);
131+
} catch (error) {
132+
console.error('Error downloading logs:', error);
133+
}
134+
};
135+
136+
const handleDeleteLog = async (selectedLogs) => {
137+
try {
138+
const selectedLogIds = Object.entries(selectedLogs)
139+
.filter(([, isSelected]) => isSelected)
140+
.map(([id]) => id);
141+
142+
if (selectedLogIds.length === 0) return;
143+
144+
const selectedLogData = logs.filter(log => selectedLogIds.includes(log.id));
145+
146+
for (const log of selectedLogData) {
147+
const { error } = await supabase
148+
.from(log.type)
149+
.delete()
150+
.eq('id', log.id);
151+
152+
if (error) throw error;
153+
}
154+
155+
// Refresh the logs list
156+
fetchLogs();
157+
} catch (error) {
158+
console.error('Error deleting logs:', error);
159+
}
160+
};
161+
162+
const handleViewLog = async (selectedLogs) => {
163+
const selectedLogIds = Object.entries(selectedLogs)
164+
.filter(([, isSelected]) => isSelected)
165+
.map(([id]) => id);
166+
167+
if (selectedLogIds.length === 0) {
168+
alert("Please select a log to view/edit");
169+
return;
170+
}
171+
if (selectedLogIds.length > 1) {
172+
alert("Please select only one log to view/edit");
173+
return;
174+
}
175+
176+
const selectedLog = logs.find(log => log.id === selectedLogIds[0]);
177+
if (selectedLog) {
178+
navigate("/manualEntry", {
179+
state: {
180+
logData: selectedLog,
181+
isEditing: true
182+
}
183+
});
184+
}
185+
};
186+
187+
/** Array of log actions */
188+
const logActions = [
189+
// {
190+
// label: "Configure",
191+
// icon: PencilSquareIcon,
192+
// onClick: () => {},
193+
// },
194+
{
195+
label: "Download",
196+
icon: ArrowDownTrayIcon,
197+
onClick: () => handleDownloadLog(selectedLogs),
198+
},
199+
// {
200+
// label: "Filter",
201+
// icon: AdjustmentsHorizontalIcon,
202+
// onClick: () => {},
203+
// },
204+
{
205+
label: "View",
206+
icon: EyeIcon,
207+
onClick: () => handleViewLog(selectedLogs),
208+
},
209+
{
210+
label: "Delete",
211+
icon: TrashIcon,
212+
onClick: () => handleDeleteLog(selectedLogs),
213+
},
214+
];
215+
117216
/** Check if all current logs are selected */
118217
const allSelected = currentLogs.every((log) => selectedLogs[log.id]);
119218

0 commit comments

Comments
 (0)