From 61a783b7ae54649770212e97de3e54bd3f1e9ef5 Mon Sep 17 00:00:00 2001 From: "Grayson, Matthew" Date: Sun, 14 Apr 2024 14:37:16 -0500 Subject: [PATCH] Separate props interface into parts; add logic to convert api response to array. --- .../components/ReadySetCyber/RSCDetail.tsx | 91 ++++------- .../components/ReadySetCyber/RSCQuestion.tsx | 151 ++++++++++++------ 2 files changed, 134 insertions(+), 108 deletions(-) diff --git a/frontend/src/components/ReadySetCyber/RSCDetail.tsx b/frontend/src/components/ReadySetCyber/RSCDetail.tsx index 0817dfd2..a4d37131 100644 --- a/frontend/src/components/ReadySetCyber/RSCDetail.tsx +++ b/frontend/src/components/ReadySetCyber/RSCDetail.tsx @@ -5,56 +5,42 @@ import Grid from '@mui/material/Grid'; import Stack from '@mui/material/Stack'; import Divider from '@mui/material/Divider'; import Button from '@mui/material/Button'; +import Typography from '@mui/material/Typography'; import { RSCSideNav } from './RSCSideNav'; -import { RSCResult } from './RSCResult'; -import { RSCQuestion } from './RSCQuestion'; -import { Typography } from '@mui/material'; +import { Category, Entry, RSCQuestion } from './RSCQuestion'; import { useAuthContext } from 'context'; export const RSCDetail: React.FC = () => { const { apiGet } = useAuthContext(); const { id } = useParams<{ id: string }>(); - const [details, setDetails] = React.useState({}); + const [categories, setCategories] = useState([]); const fetchResult = useCallback(async () => { try { const data = await apiGet(`/assessments/${id}`); - // console.log(data["Data Security"]); - // console.log(data["Data Security"][0]); - // console.log(data["Data Security"][0]["question"]); - // console.log(data["Data Security"][0]["question"].longForm); - - setDetails(data); + console.log('API Response:', data); // Continue to log the data for verification + if (data && typeof data === 'object' && !Array.isArray(data)) { + const transformedCategories = Object.entries(data).map( + ([name, entries]) => ({ + name, + entries: entries as Entry[] + }) + ); + setCategories(transformedCategories); + } else { + console.error('Unexpected response format:', data); + setCategories([]); // Fallback to an empty array if the format isn't correct + } } catch (e) { - console.error(e); + console.error('Failed to fetch categories:', e); + setCategories([]); // Ensure categories is reset to an empty array on error } }, [apiGet, id]); useEffect(() => { fetchResult(); }, [fetchResult]); - - const dataSecurity = details['Data Security']; - - // console.log("Key 0: ", Object.keys(data)[0]); - - // console.log("This is Security: ", dataSecurity[0]); - // console.log("Details: ", typeof details); - // for (const question in data) { - // console.log(question); - // } - - // Object.keys(data).forEach((key)=> { - // console.log(key, dataSecurity[key]); - // } - // ); - - // Object.keys(details).forEach((key)=> { - // console.log(key, details[key]); - // // Object.keys(details[key]).forEach((key2)=> { - // // console.log(key2, details[key][key2]); - // // }); - // }); + console.log('Transformed categories:', categories); return ( @@ -64,10 +50,10 @@ export const RSCDetail: React.FC = () => { - + @@ -79,8 +65,10 @@ export const RSCDetail: React.FC = () => { -

Thank you for completing the ReadySetCyber questionnaire!

-

+ + Thank you for completing the ReadySetCyber questionnaire! + + Below, you’ll find a full summary of your completed ReadySetCyber questionnaire. Please note the areas where you can improve your organization’s cybersecurity posture, along with @@ -90,31 +78,10 @@ export const RSCDetail: React.FC = () => { Crossfeed, CISA’s Attack Surface Management platform, for free vulnerability scanning services to kickstart or enhance your cybersecurity measures. -

- - {/* */} - - {/* {console.log("Details: ", details)} */} - {/* {details.forEach((detail) => { - <> - -
- - }); */} -
- {Object.entries(details).map(([detail]) => ( - //
- // {detail}: - //
- - ))} -
+ + {categories.map((category, index) => ( + + ))}
diff --git a/frontend/src/components/ReadySetCyber/RSCQuestion.tsx b/frontend/src/components/ReadySetCyber/RSCQuestion.tsx index 01dcc169..e7143bd0 100644 --- a/frontend/src/components/ReadySetCyber/RSCQuestion.tsx +++ b/frontend/src/components/ReadySetCyber/RSCQuestion.tsx @@ -5,59 +5,118 @@ import Stack from '@mui/material/Stack'; import Button from '@mui/material/Button'; interface Props { - category: { - question: { - id: string; - longForm: string; - number: string; - }; - selection: string; - }; + categories: Category[]; } -export const RSCQuestion: React.FC = (props) => { - const question = props.category.question; - const category = props.category; - const answers = props.category.selection; +export interface Category { + entries: Entry[]; + name: string; +} - console.log( - 'Question: ', - Object.entries(category).map(([key, value]) => ({ - key, - value - })) - ); +export interface Entry { + question: Question; + selection: string; +} + +interface Question { + description: string; + longForm: string; + name: string; + number: string; + resources: Resource[]; +} + +interface Resource { + description: string; + name: string; + type: string; + url: string; +} +export const RSCQuestion: React.FC = ({ categories }) => { return (
- - {/* - Question {question.number} - */} - - {question.longForm} - - - - - -

Recommended Resources

-

Resource Type

-
Resource Title
-

Resource Description

+ {categories.map((category, catIndex) => ( + + + {category.name} + + {category.entries.map((entry, entryIndex) => ( + + + Question {entry.question.number} + + + {entry.question.longForm} + + {entry.question.description && ( + + {entry.question.description} + + )} + + Response: {entry.selection} + + {entry.question.resources.length > 0 && ( + + + Recommended Resources + + {entry.question.resources.map((resource, resIndex) => ( + + + {resource.type} + + + {resource.name} + + + {resource.description} + + + + ))} + + )} + + ))} -
+ ))}
); };