Add category filter on risks
Signed-off-by: Antoine Bouchardy <antoine@getprobo.com> Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
committed by
Bryan Frimin
parent
b137ec6bdf
commit
c7f49c7802
@@ -43,9 +43,23 @@ import {
|
|||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/ui/switch";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
|
||||||
const defaultPageSize = 25;
|
const defaultPageSize = 25;
|
||||||
|
|
||||||
|
// Define available risk categories
|
||||||
|
const RISK_CATEGORIES = [
|
||||||
|
"Compliance & Legal",
|
||||||
|
"Cybersecurity",
|
||||||
|
"Finance",
|
||||||
|
"Human capital",
|
||||||
|
"Operations",
|
||||||
|
"Reputational",
|
||||||
|
"Strategic",
|
||||||
|
"Technology",
|
||||||
|
"Other"
|
||||||
|
] as const;
|
||||||
|
|
||||||
const listRiskViewQuery = graphql`
|
const listRiskViewQuery = graphql`
|
||||||
query ListRiskViewQuery(
|
query ListRiskViewQuery(
|
||||||
$organizationId: ID!
|
$organizationId: ID!
|
||||||
@@ -568,6 +582,9 @@ function ListRiskViewContent({
|
|||||||
// State for toggling between initial and residual risk matrix
|
// State for toggling between initial and residual risk matrix
|
||||||
const [showResidualRisk, setShowResidualRisk] = useState(false);
|
const [showResidualRisk, setShowResidualRisk] = useState(false);
|
||||||
|
|
||||||
|
// State for category filters
|
||||||
|
const [selectedCategories, setSelectedCategories] = useState<Set<string>>(new Set());
|
||||||
|
|
||||||
// Setup delete mutation
|
// Setup delete mutation
|
||||||
const [commitDeleteMutation] =
|
const [commitDeleteMutation] =
|
||||||
useMutation<ListRiskViewDeleteMutation>(deleteRiskMutation);
|
useMutation<ListRiskViewDeleteMutation>(deleteRiskMutation);
|
||||||
@@ -589,6 +606,27 @@ function ListRiskViewContent({
|
|||||||
const pageInfo = risksConnection?.risks?.pageInfo;
|
const pageInfo = risksConnection?.risks?.pageInfo;
|
||||||
const connectionId = risksConnection?.risks?.__id;
|
const connectionId = risksConnection?.risks?.__id;
|
||||||
|
|
||||||
|
// Get unique categories from existing risks
|
||||||
|
const availableCategories = Array.from(new Set(risks.map(risk => risk.category))).sort();
|
||||||
|
|
||||||
|
// Filter risks based on selected categories
|
||||||
|
const filteredRisks = selectedCategories.size === 0
|
||||||
|
? risks
|
||||||
|
: risks.filter(risk => selectedCategories.has(risk.category));
|
||||||
|
|
||||||
|
// Handle category toggle
|
||||||
|
const toggleCategory = (category: string) => {
|
||||||
|
setSelectedCategories(prev => {
|
||||||
|
const newSet = new Set(prev);
|
||||||
|
if (newSet.has(category)) {
|
||||||
|
newSet.delete(category);
|
||||||
|
} else {
|
||||||
|
newSet.add(category);
|
||||||
|
}
|
||||||
|
return newSet;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Handle delete risk
|
// Handle delete risk
|
||||||
const handleDeleteRisk = useCallback(() => {
|
const handleDeleteRisk = useCallback(() => {
|
||||||
if (!riskToDelete || !connectionId) return;
|
if (!riskToDelete || !connectionId) return;
|
||||||
@@ -700,7 +738,7 @@ function ListRiskViewContent({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<RiskMatrix
|
<RiskMatrix
|
||||||
risks={risks}
|
risks={filteredRisks}
|
||||||
isResidual={showResidualRisk}
|
isResidual={showResidualRisk}
|
||||||
organizationId={organizationId || ""}
|
organizationId={organizationId || ""}
|
||||||
/>
|
/>
|
||||||
@@ -708,6 +746,20 @@ function ListRiskViewContent({
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{/* Category Filters */}
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{availableCategories.map((category) => (
|
||||||
|
<Badge
|
||||||
|
key={category}
|
||||||
|
variant={selectedCategories.has(category) ? "default" : "outline"}
|
||||||
|
className="cursor-pointer"
|
||||||
|
onClick={() => toggleCategory(category)}
|
||||||
|
>
|
||||||
|
{category}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
<div className="w-full overflow-auto">
|
<div className="w-full overflow-auto">
|
||||||
@@ -738,7 +790,7 @@ function ListRiskViewContent({
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="[&_tr:last-child]:border-0">
|
<tbody className="[&_tr:last-child]:border-0">
|
||||||
{risks.length === 0 ? (
|
{filteredRisks.length === 0 ? (
|
||||||
<tr className="border-b transition-colors hover:bg-h-subtle-bg data-[state=selected]:bg-subtle-bg">
|
<tr className="border-b transition-colors hover:bg-h-subtle-bg data-[state=selected]:bg-subtle-bg">
|
||||||
<td
|
<td
|
||||||
colSpan={7}
|
colSpan={7}
|
||||||
@@ -748,7 +800,7 @@ function ListRiskViewContent({
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
) : (
|
) : (
|
||||||
risks.map((risk) => (
|
filteredRisks.map((risk) => (
|
||||||
<tr
|
<tr
|
||||||
key={risk.id}
|
key={risk.id}
|
||||||
className="border-b transition-colors hover:bg-h-subtle-bg data-[state=selected]:bg-subtle-bg cursor-pointer"
|
className="border-b transition-colors hover:bg-h-subtle-bg data-[state=selected]:bg-subtle-bg cursor-pointer"
|
||||||
|
|||||||
Reference in New Issue
Block a user