Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | import { utcToLocalTime } from "@/utils/helpers/utcToLocalTime";
import { Box, Divider, Stack, Typography } from "@mui/material";
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
import RemoveCircleOutlineIcon from "@mui/icons-material/RemoveCircleOutline";
/** One label/value line in the Schedule & Rules block — mirrors the student
view-assignment page's "About This Assignment" InfoRow so both pages read
the same way. */
const InfoRow = ({ label, value }) => (
<Box sx={{ display: "flex", justifyContent: "space-between", gap: 2, py: 0.75 }}>
<Typography variant="body2" color="text.secondary">
{label}
</Typography>
<Typography variant="body2" fontWeight={600} sx={{ textAlign: "right" }}>
{value}
</Typography>
</Box>
);
/** One line in the Settings block — the same single on/off icon for every
row (mirrors the student page's RuleRow) instead of a differently-colored
chip per row, so scanning the column for "what's actually on" means
reading one shape instead of several. */
const RuleRow = ({ label, enabled }) => (
<Stack direction="row" spacing={1.25} alignItems="center">
{enabled ? (
<CheckCircleIcon color="success" fontSize="small" />
) : (
<RemoveCircleOutlineIcon color="disabled" fontSize="small" />
)}
<Typography variant="body2" color={enabled ? "text.primary" : "text.secondary"}>
{label}
</Typography>
</Stack>
);
const AssignmentDetails = ({ assignmentData, section = "all" }) => {
const showSchedule = section === "all" || section === "schedule";
const showSettings = section === "all" || section === "settings";
// Support both data structures:
// 1. view-assignment: assignmentData.details, assignmentData.questions
// 2. new-assignment preview: assignmentData.step1, assignmentData.step2, assignmentData.step3
const isPreviewMode = !!assignmentData?.step1 || !!assignmentData?.step3;
// Map settings labels for both modes
const labelsViewMode = {
shuffle_questions: "Shuffle Questions",
shuffle_choices: "Shuffle Choices",
allow_calculator: "Allow Calculator",
show_score_after_submit: "Show Score After Submit",
show_correct_answers_after_submit: "Show Correct Answers After Submit",
allow_feedback_after_submit: "Allow Feedback After Submit",
};
const labelsPreviewMode = {
shuffleQuestions: "Shuffle Questions",
shuffleChoices: "Shuffle Choices",
allowCalculator: "Allow Calculator",
displayScore: "Show Score After Submit",
displayCorrectAnswers: "Show Correct Answers After Submit",
allowFeedback: "Allow Feedback After Submit",
};
const labels = isPreviewMode ? labelsPreviewMode : labelsViewMode;
// Extract data based on mode
const settings = isPreviewMode ? assignmentData?.step3 || {} : assignmentData?.details?.settings || {};
const dateOpen = isPreviewMode ? assignmentData?.step3?.dateAssigned?.dateOpen : assignmentData?.details?.date_open;
const dateClose = isPreviewMode
? assignmentData?.step3?.dateAssigned?.dateClose
: assignmentData?.details?.date_close;
const timeAllowed = isPreviewMode ? assignmentData?.step3?.timeAllowed : settings.time_allowed;
const attemptsAllowed = isPreviewMode ? assignmentData?.step3?.totalAttempts : settings.allowed_attempts;
const passingGrade = isPreviewMode ? assignmentData?.step3?.passingGrade : assignmentData?.details?.passing_grade;
const totalQuestions = isPreviewMode
? assignmentData?.step2?.selectedQuestions?.length
: assignmentData?.questions?.length;
const questions = isPreviewMode ? assignmentData?.step2?.selectedQuestions : assignmentData?.questions;
const totalPoints = questions?.reduce((sum, q) => sum + (Number(q.points) || 0), 0) || 0;
// section="all" is used standalone (Step4 preview, TestsViewAssignmentPage)
// where these blocks are their own visual unit, so they keep the bordered
// "card-like" chrome and their own subheading. section="schedule" /
// "settings" is used inside ViewAssignmentPage.jsx, where a real Card +
// SectionHeader around this component already provides that chrome —
// boxing it again would nest a card inside a card.
const blockSx =
section === "all"
? {
p: 2.5,
borderRadius: 2,
bgcolor: "background.paper",
border: "1px solid",
borderColor: "divider",
}
: {};
return (
<Stack spacing={2}>
{/* Schedule & Rules */}
{showSchedule && (
<Box sx={blockSx}>
{section === "all" && (
<Typography variant="subtitle2" fontWeight={600} sx={{ mb: 1 }}>
Schedule & Rules
</Typography>
)}
<Stack divider={<Divider />}>
<InfoRow label="Opens" value={utcToLocalTime(dateOpen)} />
<InfoRow label="Closes" value={utcToLocalTime(dateClose)} />
<InfoRow label="Time Allowed" value={timeAllowed || "Unlimited"} />
<InfoRow label="Attempts Allowed" value={attemptsAllowed || "Unlimited"} />
<InfoRow label="Passing Grade" value={passingGrade ? `${passingGrade}%` : "N/A"} />
<InfoRow label="Total Questions" value={totalQuestions || 0} />
<InfoRow label="Total Points" value={totalPoints} />
</Stack>
</Box>
)}
{/* Settings */}
{showSettings && (
<Box sx={blockSx}>
{section === "all" && (
<Typography variant="subtitle2" fontWeight={600} sx={{ mb: 1 }}>
Settings
</Typography>
)}
<Stack spacing={1.5}>
{Object.entries(labels).map(([key, label]) => (
<RuleRow key={key} label={label} enabled={!!settings[key]} />
))}
</Stack>
</Box>
)}
</Stack>
);
};
export default AssignmentDetails;
|