+ {flow.steps.map(step => {
+ const totalApprovers = step.levels.reduce((n, l) => n + l.approvers.length, 0)
+ return (
+
+
+
+ Bước {step.order} — {step.name}
+
+ {step.departmentName && (
+
+ {step.departmentName}
+
+ )}
+ {totalApprovers > 1 && (
+
+ ({totalApprovers} người duyệt)
+
+ )}
+
+
+ {step.levels.flatMap(level =>
+ level.approvers.map(approver => {
+ const opinion = opinions.find(o =>
+ o.stepOrder === step.order
+ && o.levelOrder === level.order
+ && o.approverUserId === approver.userId,
+ ) ?? null
+ return (
+
+ )
+ }),
+ )}
+
+
+ )
+ })}
+
+ )
+}
+
+function LevelOpinionBox({
+ levelOrder,
+ approverUserId,
+ approverName,
+ opinion,
+}: {
+ levelOrder: number
+ approverUserId: string
+ approverName: string
+ opinion: PeLevelOpinion | null
+}) {
+ const isSigned = !!opinion
+ const isAdminOverride = isSigned && opinion!.signedByUserId !== approverUserId
+
+ return (
+