From 628db6d4de5578fd6d0a5ad217f4ed8dfaaf5044 Mon Sep 17 00:00:00 2001
From: Justin Glotzbach <20047549+justinglotz@users.noreply.github.com>
Date: Thu, 18 Dec 2025 18:52:29 -0600
Subject: [PATCH 1/3] feat: added filters for issues view
---
client/src/Components/IssueFilters.jsx | 70 ++++++++++++
client/src/Pages/Issues.jsx | 147 ++++++++++++++++++++-----
2 files changed, 188 insertions(+), 29 deletions(-)
create mode 100644 client/src/Components/IssueFilters.jsx
diff --git a/client/src/Components/IssueFilters.jsx b/client/src/Components/IssueFilters.jsx
new file mode 100644
index 0000000..5f354b8
--- /dev/null
+++ b/client/src/Components/IssueFilters.jsx
@@ -0,0 +1,70 @@
+export const IssueFilters = ({ filters, onFilterChange }) => {
+ return (
+
+ {/* Status filter */}
+
+
+ {/* Priority filter */}
+
+
+ {/* Category filter */}
+
+
+ {/* Date filter */}
+
+ onFilterChange("startDate", e.target.value)}
+ className="border rounded px-3 py-2 mr-2"
+ />
+ to
+ onFilterChange("endDate", e.target.value)}
+ className="border rounded px-3 py-2"
+ />
+
+
+ );
+};
diff --git a/client/src/Pages/Issues.jsx b/client/src/Pages/Issues.jsx
index 59f0520..3b36be3 100644
--- a/client/src/Pages/Issues.jsx
+++ b/client/src/Pages/Issues.jsx
@@ -1,7 +1,8 @@
-import { useState, useEffect } from 'react';
-import IssueCard from '../components/IssueCard';
-import IssueForm from '../Components/issueForm';
-import { issueAPI } from '../services/api';
+import { useState, useEffect } from "react";
+import IssueCard from "../components/IssueCard";
+import IssueForm from "../Components/issueForm";
+import { issueAPI } from "../services/api";
+import { IssueFilters } from "../Components/IssueFilters";
const Issues = () => {
const [showForm, setShowForm] = useState(false);
@@ -9,10 +10,17 @@ const Issues = () => {
const [loading, setLoading] = useState(true);
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState(null);
+ const [filters, setFilters] = useState({
+ status: "all",
+ priority: "all",
+ category: "all",
+ startDate: "",
+ endDate: "",
+ });
// Fetch issues when component mounts
useEffect(() => {
- fetchIssues();
+ fetchIssues();
}, []);
const fetchIssues = async () => {
@@ -22,8 +30,8 @@ const Issues = () => {
const data = await issueAPI.getAllIssues();
setIssues(data);
} catch (err) {
- console.error('Failed to fetch issues:', err);
- setError('Failed to load issues. Please try again later.');
+ console.error("Failed to fetch issues:", err);
+ setError("Failed to load issues. Please try again later.");
} finally {
setLoading(false);
}
@@ -33,24 +41,61 @@ const Issues = () => {
try {
setSubmitting(true);
setError(null);
-
+
// Call the API to create the issue
const createdIssue = await issueAPI.createIssue(newIssue);
-
+
// Add the new issue to the list
setIssues([createdIssue, ...issues]);
setShowForm(false);
-
+
// Show success message (you could use a toast notification library)
- alert('Issue submitted successfully!');
+ alert("Issue submitted successfully!");
} catch (err) {
- console.error('Failed to submit issue:', err);
- setError('Failed to submit issue. Please try again.');
+ console.error("Failed to submit issue:", err);
+ setError("Failed to submit issue. Please try again.");
// Don't close the form so user can retry
} finally {
setSubmitting(false);
}
};
+ // filterKey, value
+ const handleFiltersChange = (filterKey, value) => {
+ setFilters({
+ ...filters,
+ [filterKey]: value,
+ });
+ };
+
+ // Filter issues based on current filters
+ const filteredIssues = issues.filter((issue) => {
+ // Status filter
+ if (filters.status !== "all" && issue.status !== filters.status) {
+ return false;
+ }
+ // Priority filter
+ if (filters.priority !== "all" && issue.priority !== filters.priority) {
+ return false;
+ }
+ // Category filter
+ if (filters.category !== "all" && issue.category !== filters.category) {
+ return false;
+ }
+ // Date range filter (assuming issue has createdAt field)
+ if (
+ filters.startDate &&
+ new Date(issue.createdAt) < new Date(filters.startDate)
+ ) {
+ return false;
+ }
+ if (
+ filters.endDate &&
+ new Date(issue.createdAt) > new Date(filters.endDate)
+ ) {
+ return false;
+ }
+ return true;
+ });
return (
@@ -61,20 +106,28 @@ const Issues = () => {
disabled={loading}
className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 disabled:bg-blue-400 disabled:cursor-not-allowed transition-colors"
>
- {showForm ? 'View Issues' : 'Report New Issue'}
+ {showForm ? "View Issues" : "Report New Issue"}
{/* Error Message */}
{error && (
-
diff --git a/client/src/Pages/Issues.jsx b/client/src/Pages/Issues.jsx
index 3b36be3..846c664 100644
--- a/client/src/Pages/Issues.jsx
+++ b/client/src/Pages/Issues.jsx
@@ -84,13 +84,14 @@ const Issues = () => {
// Date range filter (assuming issue has createdAt field)
if (
filters.startDate &&
- new Date(issue.createdAt) < new Date(filters.startDate)
+ new Date(issue.createdAt) < new Date(filters.startDate + "T00:00:00")
) {
return false;
}
+
if (
filters.endDate &&
- new Date(issue.createdAt) > new Date(filters.endDate)
+ new Date(issue.createdAt) > new Date(filters.endDate + "T23:59:59")
) {
return false;
}
From 0c9613e71e99ac723ab34e7489c09c786ecd5860 Mon Sep 17 00:00:00 2001
From: Justin Glotzbach <20047549+justinglotz@users.noreply.github.com>
Date: Thu, 18 Dec 2025 21:46:12 -0600
Subject: [PATCH 3/3] added workflow to add automatic slack messages when a new
PR is opened
---
.github/workflows/pr-notification.yml | 57 +++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
create mode 100644 .github/workflows/pr-notification.yml
diff --git a/.github/workflows/pr-notification.yml b/.github/workflows/pr-notification.yml
new file mode 100644
index 0000000..9913f8a
--- /dev/null
+++ b/.github/workflows/pr-notification.yml
@@ -0,0 +1,57 @@
+name: Slack PR Notification
+
+on:
+ pull_request:
+ types: [opened]
+
+jobs:
+ notify-slack:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Send Slack Notification
+ uses: slackapi/slack-github-action@v1.26.0
+ with:
+ payload: |
+ {
+ "text": "New Pull Request: ${{ github.event.pull_request.title }}",
+ "blocks": [
+ {
+ "type": "header",
+ "text": {
+ "type": "plain_text",
+ "text": "🔔 New Pull Request"
+ }
+ },
+ {
+ "type": "section",
+ "fields": [
+ {
+ "type": "mrkdwn",
+ "text": "*Title:*\n${{ github.event.pull_request.title }}"
+ },
+ {
+ "type": "mrkdwn",
+ "text": "*Author:*\n${{ github.event.pull_request.user.login }}"
+ },
+ {
+ "type": "mrkdwn",
+ "text": "*Repository:*\n${{ github.repository }}"
+ },
+ {
+ "type": "mrkdwn",
+ "text": "*Branch:*\n${{ github.event.pull_request.head.ref }}"
+ }
+ ]
+ },
+ {
+ "type": "section",
+ "text": {
+ "type": "mrkdwn",
+ "text": "<${{ github.event.pull_request.html_url }}|View Pull Request>"
+ }
+ }
+ ]
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+ SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK