([]);
+
+ async function fetchCsvData() {
+ setLoading(true);
+ try {
+ const response = await fetch('/api/fetchCsv');
+ const data = await response.json();
+ console.log('Fetched CSV data:', data);
+ setData(data);
+ } catch (error) {
+ console.error("Failed to fetch CSV data:", error);
+ }
+ setLoading(false);
+ }
+
+ useEffect(() => {
+ //fetchCsvData();
+ fetchWorkgroups(); // Add this line
+ }, []);
+
+ async function fetchWorkgroups() {
+ try {
+ const databaseWorkgroups = await getWorkgroups();
+ const allSummaries = await getMissingSummaries();
+ setAllSummaries(allSummaries)
+
+ // Assuming databaseWorkgroups should be an array, check and handle accordingly
+ if (Array.isArray(databaseWorkgroups)) {
+ setWorkgroups(databaseWorkgroups);
+ } else {
+ console.error("Expected an array for workgroups, received:", databaseWorkgroups);
+ // Handle the unexpected format, e.g., set to an empty array or a default value
+ setWorkgroups([]);
+ }
+ } catch (error) {
+ console.error("Error fetching workgroups:", error);
+ setWorkgroups([]); // Handle error by setting workgroups to an empty array or another default state
+ }
+ }
+
+ return (
+
+
+ Status of Summaries
+ {loading && Loading...
}
+
+
+ {/* Missing Summaries Table */}
+
Missing Summaries
+
+
+
+ | Meeting Date |
+ Workgroup |
+ Status |
+
+
+
+ {allSummaries.filter(row => row.status === "Missing").map((row, index) => (
+
+ | {row.meetingDate} |
+ {row.workgroup} |
+ {row.status} |
+
+ ))}
+
+
+
+ {/* Done Summaries Table */}
+
Done Summaries
+
+
+
+ | Meeting Date |
+ Workgroup |
+ Status |
+
+
+
+ {allSummaries.filter(row => row.status === "Done").map((row, index) => (
+
+ | {row.meetingDate} |
+ {row.workgroup} |
+ {row.status} |
+
+ ))}
+
+
+
+
+ );
+};
+
+export default StatusOfSummaries;
diff --git a/pages/submit-meeting-summary/index.tsx b/pages/submit-meeting-summary/index.tsx
index 266f453..af9b8da 100644
--- a/pages/submit-meeting-summary/index.tsx
+++ b/pages/submit-meeting-summary/index.tsx
@@ -220,6 +220,17 @@ useEffect(() => {
});
};
+ const resetSummary = () => {
+ setMyVariable(prevMyVariable => ({
+ ...prevMyVariable,
+ summary: {
+ ...prevMyVariable.summary,
+ meetingInfo: {},
+ agendaItems: [],
+ tags: {}
+ }
+ }));
+ };
return (
@@ -277,6 +288,12 @@ useEffect(() => {
{selectedWorkgroupId && (<>
{myVariable.roles?.isAdmin && ()}
{myVariable.roles?.isAdmin && }
+
>)}
{myVariable.isLoggedIn && selectedWorkgroupId && (
diff --git a/styles/SubmitMissingSummary.module.css b/styles/SubmitMissingSummary.module.css
new file mode 100644
index 0000000..e321e63
--- /dev/null
+++ b/styles/SubmitMissingSummary.module.css
@@ -0,0 +1,20 @@
+.container {
+ margin-top: 50px;
+ margin-bottom: 20px;
+}
+
+.formGroup {
+ margin-bottom: 10px;
+}
+
+.submitButton {
+ background-color: #4CAF50;
+ color: white;
+ padding: 10px 20px;
+ border: none;
+ cursor: pointer;
+}
+
+.submitButton:hover {
+ background-color: #45a049;
+}
diff --git a/styles/meetingsummary.module.css b/styles/meetingsummary.module.css
index f42d277..2cb084e 100644
--- a/styles/meetingsummary.module.css
+++ b/styles/meetingsummary.module.css
@@ -95,6 +95,24 @@
font-size: 1rem;
}
+.resetButton {
+ width: 170px;
+ display: block;
+ padding: 0.5rem;
+ margin: 0.5rem 0;
+ text-align: center;
+ background-color: rgb(18, 105, 198);
+ border: none;
+ cursor: pointer;
+ color: white;
+ z-index: 9999;
+ font-size: 1rem;
+}
+.resetButton:hover {
+ background-color: rgb(13, 64, 120);
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
.navButton:focus {
outline: 4px auto -webkit-focus-ring-color;
}
diff --git a/styles/summariestable.module.css b/styles/summariestable.module.css
new file mode 100644
index 0000000..af397d5
--- /dev/null
+++ b/styles/summariestable.module.css
@@ -0,0 +1,65 @@
+.container {
+ color: #fff; /* White text color for better readability */
+ background-color: black; /* Assuming your background is black */
+ padding: 20px;
+}
+
+.issuesTable {
+ width: 100%;
+ border-collapse: collapse;
+ margin-bottom: 20px;
+ table-layout: fixed; /* Add this line */
+}
+
+.tableHeader, .tableData {
+ text-align: left;
+ padding: 8px;
+ border-bottom: 1px solid #ddd; /* Light grey border for some contrast */
+}
+
+.tableHeader {
+ background-color: #333; /* Darker background for headers */
+ color: #fff;
+}
+
+/* Specify column widths */
+.tableHeader:nth-child(1) {
+ width: 30%; /* Adjust based on your preference */
+}
+
+.tableHeader:nth-child(2) {
+ width: 50%; /* Adjust based on your preference */
+}
+
+.tableHeader:nth-child(3) {
+ width: 20%; /* Adjust based on your preference */
+}
+
+.tableRow:hover {
+ background-color: #555; /* Slightly lighter row background on hover */
+}
+
+.missingHeading {
+ color: rgb(194, 129, 254); /* Golden color for headings */
+}
+
+.doneHeading {
+ color: rgb(0, 255, 221); /* Golden color for headings */
+}
+
+.createIssueButton {
+ background-color: #4CAF50; /* Green background */
+ color: white;
+ padding: 10px 20px;
+ margin: 10px 0;
+ border: none;
+ cursor: pointer;
+}
+
+.createIssueButton:hover {
+ background-color: #45a049;
+}
+
+.issuesTableContainer {
+ overflow-x: auto;
+}
diff --git a/utils/getMissingSummaries.js b/utils/getMissingSummaries.js
new file mode 100644
index 0000000..77497fc
--- /dev/null
+++ b/utils/getMissingSummaries.js
@@ -0,0 +1,78 @@
+import { supabase } from "../lib/supabaseClient";
+
+function formatDate(dateString) {
+ const options = { year: 'numeric', month: 'long', day: 'numeric' };
+ const date = new Date(dateString);
+ // Manually construct the date string to ensure it's in "DD MMMM YYYY" format
+ const formattedDate = `${date.getDate()} ${date.toLocaleString('en-US', { month: 'long' })} ${date.getFullYear()}`;
+ return formattedDate;
+}
+
+export async function getMissingSummaries() {
+ let missingSummaries = [];
+ let allDoneSummaries = [];
+
+ async function getAllMissingSummaries() {
+ try {
+ const { data, error, status } = await supabase
+ .from('missingsummaries')
+ .select('workgroup, meeting_date, status');
+
+ if (error && status !== 406) throw error;
+ if (data) {
+ missingSummaries = data.map(item => ({
+ ...item,
+ meetingDate: item.meeting_date,
+ status: item.status,
+ workgroup: item.workgroup
+ }));
+ }
+ } catch (error) {
+ console.log("error", error.message);
+ }
+ }
+
+ async function getAllSummaries() {
+ try {
+ const { data, error, status } = await supabase
+ .from('meetingsummaries')
+ .select('date, summary')
+ .order('date', { ascending: false });
+
+ if (error && status !== 406) throw error;
+ if (data) {
+ allDoneSummaries = data.map(item => ({
+ meetingDate: formatDate(item.date),
+ status: "Done", // Setting status to "Done" for all done summaries
+ workgroup: item.summary.workgroup
+ }));
+ }
+ } catch (error) {
+ console.log("error", error.message);
+ }
+ }
+
+ await getAllMissingSummaries();
+ await getAllSummaries();
+
+ const combinedSummaries = [...missingSummaries, ...allDoneSummaries];
+ const uniqueSummariesMap = new Map();
+
+ combinedSummaries.forEach(summary => {
+ const key = `${summary.meetingDate}-${summary.workgroup}`;
+ // Check if the map already has an entry for this key
+ if (uniqueSummariesMap.has(key)) {
+ // Prioritize "Done" summaries over "Missing"
+ const existingSummary = uniqueSummariesMap.get(key);
+ if (existingSummary.status !== "Done" && summary.status === "Done") {
+ uniqueSummariesMap.set(key, summary);
+ }
+ } else {
+ uniqueSummariesMap.set(key, summary);
+ }
+ });
+
+ const finalSummaries = Array.from(uniqueSummariesMap.values());
+
+ return finalSummaries;
+ }
\ No newline at end of file
diff --git a/utils/getsummaries.js b/utils/getsummaries.js
index 5d9f7b7..a21266e 100644
--- a/utils/getsummaries.js
+++ b/utils/getsummaries.js
@@ -49,9 +49,9 @@ export async function getSummaries(workgroup_id) {
// Fetch the user details for each summary
for (const data of summaryData) {
// Exclude meetings where confirmed == true and all meetings with an earlier date and updated_at date than the last meeting where confirmed == true
- if (data.confirmed === true || new Date(data.date) < new Date(lastConfirmedDate)) { //Might have to add this back in later - || new Date(data.updated_at) < new Date(lastUpdatedAt)
+ /*if (data.confirmed === true || new Date(data.date) < new Date(lastConfirmedDate)) { //Might have to add this back in later - || new Date(data.updated_at) < new Date(lastUpdatedAt)
continue;
- }
+ }*/
const { data: userData, error: userError } = await supabase
.from('users')
diff --git a/utils/saveMissingSummaries.js b/utils/saveMissingSummaries.js
new file mode 100644
index 0000000..2a8aaef
--- /dev/null
+++ b/utils/saveMissingSummaries.js
@@ -0,0 +1,23 @@
+import { supabase } from "../lib/supabaseClient";
+
+export async function saveMissingSummary(summaryData) {
+ let updates = {
+ workgroup_id: summaryData.workgroupId,
+ workgroup: summaryData.workgroup,
+ meeting_date: summaryData.meetingDate,
+ status: summaryData.status,
+ type: summaryData.type
+ }
+
+ const { data, error } = await supabase
+ .from('missingsummaries')
+ .upsert(updates, { onConflict: ['workgroup_id', 'meeting_date', 'type'] })
+ .select('meeting_date, workgroup, updated_at');
+
+ if (error) {
+ console.error('Error upserting data:', error);
+ return false;
+ }
+
+ return data;
+}
diff --git a/utils/updateCSVInGitHub.js b/utils/updateCSVInGitHub.js
new file mode 100644
index 0000000..08b034f
--- /dev/null
+++ b/utils/updateCSVInGitHub.js
@@ -0,0 +1,89 @@
+// File: utils/githubCSVUtils.js
+import { Octokit } from "@octokit/rest";
+
+const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
+
+export const fetchAndUpdateCSV = async ({ owner, repo, path, branch = 'main', summariesToUpdate }) => {
+ // Fetch the current CSV content
+ const { data: fileData } = await octokit.repos.getContent({
+ owner,
+ repo,
+ path,
+ ref: branch,
+ });
+ const currentCSV = Buffer.from(fileData.content, 'base64').toString('utf8');
+
+ // Update the CSV content based on allSummaries
+ const updatedCSV = updateCSVContent(currentCSV, summariesToUpdate);
+
+ // Encode the updated CSV content in Base64 for GitHub
+ const contentEncoded = Buffer.from(updatedCSV).toString('base64');
+
+ // Update the file on GitHub
+ const { data: updateResponse } = await octokit.repos.createOrUpdateFileContents({
+ owner,
+ repo,
+ path,
+ message: "Update CSV with new summaries",
+ content: contentEncoded,
+ sha: fileData.sha,
+ branch,
+ });
+
+ return updateResponse;
+};
+
+const updateCSVContent = (currentCSV, summariesToUpdate) => {
+ const lines = currentCSV.split('\n').filter(line => line.trim()); // Exclude empty lines
+ const headers = lines.shift().split(','); // Extract headers
+ let csvObjects = lines.map(line => line.split(',').reduce((acc, cur, i) => ({
+ ...acc,
+ [headers[i]]: cur,
+ }), {}));
+
+ // Create a map of existing summaries for quick lookup
+ let existingSummariesMap = new Map(csvObjects.map(obj => [`${obj.meetingDate}-${obj.workgroup}`, obj]));
+
+ // Iterate over allSummaries to update existing or add new entries
+ summariesToUpdate.forEach(summary => {
+ const key = `${summary.meetingDate}-${summary.workgroup}`;
+ if (existingSummariesMap.has(key)) {
+ // Update existing entry
+ const existingEntry = existingSummariesMap.get(key);
+ existingEntry.status = summary.status; // Assuming status is the field to update
+ } else {
+ // Add new entry
+ existingSummariesMap.set(key, summary);
+ }
+ });
+
+ // Convert the updated map back to CSV string
+ const updatedCSVObjects = Array.from(existingSummariesMap.values());
+ // Function to parse custom date format into a Date object
+ function parseCustomDate(dateString) {
+ const [day, month, year] = dateString.split(' ');
+ const monthIndex = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"].indexOf(month);
+ return new Date(year, monthIndex, day);
+ }
+
+ // Sort the objects by status ("Missing" at the top), then by date in descending order
+ updatedCSVObjects.sort((a, b) => {
+ // Sort by status
+ if (a.status === "Missing" && b.status !== "Missing") {
+ return -1;
+ } else if (a.status !== "Missing" && b.status === "Missing") {
+ return 1;
+ }
+
+ // Then sort by date within the same status group
+ const dateA = parseCustomDate(a.meetingDate);
+ const dateB = parseCustomDate(b.meetingDate);
+ return dateB - dateA; // Descending order
+ });
+
+ // Convert sorted objects back to CSV lines
+ const updatedCSVLines = updatedCSVObjects.map(obj => headers.map(header => obj[header] || "").join(','));
+ const updatedCSV = [headers.join(',')].concat(updatedCSVLines).join('\n');
+
+ return updatedCSV;
+};
\ No newline at end of file