@tipp/ui 2.8.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (568) hide show
  1. package/dist/app/index.cjs +49 -4
  2. package/dist/app/index.cjs.map +1 -1
  3. package/dist/app/index.js +98 -97
  4. package/dist/app/platform/coach-question-list.cjs +49 -4
  5. package/dist/app/platform/coach-question-list.cjs.map +1 -1
  6. package/dist/app/platform/coach-question-list.js +33 -32
  7. package/dist/app/platform/contents-card.cjs +49 -4
  8. package/dist/app/platform/contents-card.cjs.map +1 -1
  9. package/dist/app/platform/contents-card.js +33 -32
  10. package/dist/app/platform/curriculum-card.cjs +49 -4
  11. package/dist/app/platform/curriculum-card.cjs.map +1 -1
  12. package/dist/app/platform/curriculum-card.js +5 -4
  13. package/dist/app/platform/edit-coaching-time.cjs +49 -4
  14. package/dist/app/platform/edit-coaching-time.cjs.map +1 -1
  15. package/dist/app/platform/edit-coaching-time.js +80 -79
  16. package/dist/app/platform/edit-service-type.cjs +49 -4
  17. package/dist/app/platform/edit-service-type.cjs.map +1 -1
  18. package/dist/app/platform/edit-service-type.js +81 -80
  19. package/dist/app/platform/goal-manage-card-edit.cjs +49 -4
  20. package/dist/app/platform/goal-manage-card-edit.cjs.map +1 -1
  21. package/dist/app/platform/goal-manage-card-edit.js +80 -79
  22. package/dist/app/platform/goal-manage-card-read.cjs +49 -4
  23. package/dist/app/platform/goal-manage-card-read.cjs.map +1 -1
  24. package/dist/app/platform/goal-manage-card-read.js +33 -32
  25. package/dist/app/platform/on-offline-radio-card.cjs +49 -4
  26. package/dist/app/platform/on-offline-radio-card.cjs.map +1 -1
  27. package/dist/app/platform/on-offline-radio-card.js +80 -79
  28. package/dist/app/platform/report-card.cjs +49 -4
  29. package/dist/app/platform/report-card.cjs.map +1 -1
  30. package/dist/app/platform/report-card.js +33 -32
  31. package/dist/app/platform/reservation-card.cjs +49 -4
  32. package/dist/app/platform/reservation-card.cjs.map +1 -1
  33. package/dist/app/platform/reservation-card.js +81 -80
  34. package/dist/app/platform/session-card.cjs +49 -4
  35. package/dist/app/platform/session-card.cjs.map +1 -1
  36. package/dist/app/platform/session-card.js +83 -82
  37. package/dist/app/platform/session-review-simple-read.cjs +49 -4
  38. package/dist/app/platform/session-review-simple-read.cjs.map +1 -1
  39. package/dist/app/platform/session-review-simple-read.js +33 -32
  40. package/dist/app/platform/userInfos/coaching-customer-info/index.cjs +49 -4
  41. package/dist/app/platform/userInfos/coaching-customer-info/index.cjs.map +1 -1
  42. package/dist/app/platform/userInfos/coaching-customer-info/index.js +36 -35
  43. package/dist/app/platform/userInfos/coaching-customer-info/large.cjs +49 -4
  44. package/dist/app/platform/userInfos/coaching-customer-info/large.cjs.map +1 -1
  45. package/dist/app/platform/userInfos/coaching-customer-info/large.js +33 -32
  46. package/dist/app/platform/userInfos/coaching-customer-info/medium.cjs +49 -4
  47. package/dist/app/platform/userInfos/coaching-customer-info/medium.cjs.map +1 -1
  48. package/dist/app/platform/userInfos/coaching-customer-info/medium.js +33 -32
  49. package/dist/app/platform/userInfos/coaching-customer-info/small.cjs +49 -4
  50. package/dist/app/platform/userInfos/coaching-customer-info/small.cjs.map +1 -1
  51. package/dist/app/platform/userInfos/coaching-customer-info/small.js +33 -32
  52. package/dist/app/platform/userInfos/session-user-info-detail.cjs +49 -4
  53. package/dist/app/platform/userInfos/session-user-info-detail.cjs.map +1 -1
  54. package/dist/app/platform/userInfos/session-user-info-detail.js +33 -32
  55. package/dist/app/platform/userInfos/utils.cjs +49 -4
  56. package/dist/app/platform/userInfos/utils.cjs.map +1 -1
  57. package/dist/app/platform/userInfos/utils.js +32 -31
  58. package/dist/app/roleplay/chart/session-chart.cjs +351 -0
  59. package/dist/app/roleplay/chart/session-chart.cjs.map +1 -0
  60. package/dist/app/roleplay/chart/session-chart.d.cts +16 -0
  61. package/dist/app/roleplay/chart/session-chart.d.ts +16 -0
  62. package/dist/app/roleplay/chart/session-chart.js +14 -0
  63. package/dist/app/roleplay/index.cjs +5706 -0
  64. package/dist/app/roleplay/index.cjs.map +1 -0
  65. package/dist/app/roleplay/index.d.cts +4 -0
  66. package/dist/app/roleplay/index.d.ts +4 -0
  67. package/dist/app/roleplay/index.js +182 -0
  68. package/dist/app/roleplay/index.js.map +1 -0
  69. package/dist/app/roleplay/parts/analysis-section.cjs +2178 -0
  70. package/dist/app/roleplay/parts/analysis-section.cjs.map +1 -0
  71. package/dist/app/roleplay/parts/analysis-section.d.cts +17 -0
  72. package/dist/app/roleplay/parts/analysis-section.d.ts +17 -0
  73. package/dist/app/roleplay/parts/analysis-section.js +97 -0
  74. package/dist/app/roleplay/parts/analysis-section.js.map +1 -0
  75. package/dist/app/roleplay/parts/coaching-panel.cjs +2191 -0
  76. package/dist/app/roleplay/parts/coaching-panel.cjs.map +1 -0
  77. package/dist/app/roleplay/parts/coaching-panel.d.cts +8 -0
  78. package/dist/app/roleplay/parts/coaching-panel.d.ts +8 -0
  79. package/dist/app/roleplay/parts/coaching-panel.js +95 -0
  80. package/dist/app/roleplay/parts/coaching-panel.js.map +1 -0
  81. package/dist/app/roleplay/parts/content.cjs +4683 -0
  82. package/dist/app/roleplay/parts/content.cjs.map +1 -0
  83. package/dist/app/roleplay/parts/content.d.cts +15 -0
  84. package/dist/app/roleplay/parts/content.d.ts +15 -0
  85. package/dist/app/roleplay/parts/content.js +174 -0
  86. package/dist/app/roleplay/parts/content.js.map +1 -0
  87. package/dist/app/roleplay/parts/header.cjs +2300 -0
  88. package/dist/app/roleplay/parts/header.cjs.map +1 -0
  89. package/dist/app/roleplay/parts/header.d.cts +13 -0
  90. package/dist/app/roleplay/parts/header.d.ts +13 -0
  91. package/dist/app/roleplay/parts/header.js +96 -0
  92. package/dist/app/roleplay/parts/header.js.map +1 -0
  93. package/dist/app/roleplay/parts/score-summary.cjs +2276 -0
  94. package/dist/app/roleplay/parts/score-summary.cjs.map +1 -0
  95. package/dist/app/roleplay/parts/score-summary.d.cts +12 -0
  96. package/dist/app/roleplay/parts/score-summary.d.ts +12 -0
  97. package/dist/app/roleplay/parts/score-summary.js +96 -0
  98. package/dist/app/roleplay/parts/score-summary.js.map +1 -0
  99. package/dist/app/roleplay/parts/score-trend-section.cjs +3686 -0
  100. package/dist/app/roleplay/parts/score-trend-section.cjs.map +1 -0
  101. package/dist/app/roleplay/parts/score-trend-section.d.cts +14 -0
  102. package/dist/app/roleplay/parts/score-trend-section.d.ts +14 -0
  103. package/dist/app/roleplay/parts/score-trend-section.js +168 -0
  104. package/dist/app/roleplay/parts/score-trend-section.js.map +1 -0
  105. package/dist/app/roleplay/parts/script-transcript.cjs +2288 -0
  106. package/dist/app/roleplay/parts/script-transcript.cjs.map +1 -0
  107. package/dist/app/roleplay/parts/script-transcript.d.cts +15 -0
  108. package/dist/app/roleplay/parts/script-transcript.d.ts +15 -0
  109. package/dist/app/roleplay/parts/script-transcript.js +96 -0
  110. package/dist/app/roleplay/parts/script-transcript.js.map +1 -0
  111. package/dist/app/roleplay/parts/section-nav.cjs +2433 -0
  112. package/dist/app/roleplay/parts/section-nav.cjs.map +1 -0
  113. package/dist/app/roleplay/parts/section-nav.d.cts +15 -0
  114. package/dist/app/roleplay/parts/section-nav.d.ts +15 -0
  115. package/dist/app/roleplay/parts/section-nav.js +96 -0
  116. package/dist/app/roleplay/parts/section-nav.js.map +1 -0
  117. package/dist/app/roleplay/parts/session-replay-dialog.cjs +2598 -0
  118. package/dist/app/roleplay/parts/session-replay-dialog.cjs.map +1 -0
  119. package/dist/app/roleplay/parts/session-replay-dialog.d.cts +14 -0
  120. package/dist/app/roleplay/parts/session-replay-dialog.d.ts +14 -0
  121. package/dist/app/roleplay/parts/session-replay-dialog.js +97 -0
  122. package/dist/app/roleplay/parts/session-replay-dialog.js.map +1 -0
  123. package/dist/app/roleplay/parts/step-detail.cjs +2311 -0
  124. package/dist/app/roleplay/parts/step-detail.cjs.map +1 -0
  125. package/dist/app/roleplay/parts/step-detail.d.cts +9 -0
  126. package/dist/app/roleplay/parts/step-detail.d.ts +9 -0
  127. package/dist/app/roleplay/parts/step-detail.js +96 -0
  128. package/dist/app/roleplay/parts/step-detail.js.map +1 -0
  129. package/dist/app/roleplay/parts/step-radar.cjs +463 -0
  130. package/dist/app/roleplay/parts/step-radar.cjs.map +1 -0
  131. package/dist/app/roleplay/parts/step-radar.d.cts +8 -0
  132. package/dist/app/roleplay/parts/step-radar.d.ts +8 -0
  133. package/dist/app/roleplay/parts/step-radar.js +14 -0
  134. package/dist/app/roleplay/parts/step-radar.js.map +1 -0
  135. package/dist/app/roleplay/parts/step-summary.cjs +2651 -0
  136. package/dist/app/roleplay/parts/step-summary.cjs.map +1 -0
  137. package/dist/app/roleplay/parts/step-summary.d.cts +8 -0
  138. package/dist/app/roleplay/parts/step-summary.d.ts +8 -0
  139. package/dist/app/roleplay/parts/step-summary.js +101 -0
  140. package/dist/app/roleplay/parts/step-summary.js.map +1 -0
  141. package/dist/app/roleplay/rp-session-detail.cjs +5703 -0
  142. package/dist/app/roleplay/rp-session-detail.cjs.map +1 -0
  143. package/dist/app/roleplay/rp-session-detail.d.cts +17 -0
  144. package/dist/app/roleplay/rp-session-detail.d.ts +17 -0
  145. package/dist/app/roleplay/rp-session-detail.js +179 -0
  146. package/dist/app/roleplay/rp-session-detail.js.map +1 -0
  147. package/dist/app/roleplay/types.cjs +19 -0
  148. package/dist/app/roleplay/types.cjs.map +1 -0
  149. package/dist/app/roleplay/types.d.cts +42 -0
  150. package/dist/app/roleplay/types.d.ts +42 -0
  151. package/dist/app/roleplay/types.js +2 -0
  152. package/dist/app/roleplay/types.js.map +1 -0
  153. package/dist/app/roleplay/utils/report-parse.cjs +285 -0
  154. package/dist/app/roleplay/utils/report-parse.cjs.map +1 -0
  155. package/dist/app/roleplay/utils/report-parse.d.cts +57 -0
  156. package/dist/app/roleplay/utils/report-parse.d.ts +57 -0
  157. package/dist/app/roleplay/utils/report-parse.js +8 -0
  158. package/dist/app/roleplay/utils/report-parse.js.map +1 -0
  159. package/dist/app/roleplay/utils/report-parse.test.cjs +491 -0
  160. package/dist/app/roleplay/utils/report-parse.test.cjs.map +1 -0
  161. package/dist/app/roleplay/utils/report-parse.test.d.cts +2 -0
  162. package/dist/app/roleplay/utils/report-parse.test.d.ts +2 -0
  163. package/dist/app/roleplay/utils/report-parse.test.js +237 -0
  164. package/dist/app/roleplay/utils/report-parse.test.js.map +1 -0
  165. package/dist/app/roleplay/utils/session-utils.cjs +204 -0
  166. package/dist/app/roleplay/utils/session-utils.cjs.map +1 -0
  167. package/dist/app/roleplay/utils/session-utils.d.cts +38 -0
  168. package/dist/app/roleplay/utils/session-utils.d.ts +38 -0
  169. package/dist/app/roleplay/utils/session-utils.js +46 -0
  170. package/dist/app/roleplay/utils/session-utils.js.map +1 -0
  171. package/dist/atoms/bullet-text.cjs +29 -2
  172. package/dist/atoms/bullet-text.cjs.map +1 -1
  173. package/dist/atoms/bullet-text.js +3 -2
  174. package/dist/atoms/dialog.cjs +29 -2
  175. package/dist/atoms/dialog.cjs.map +1 -1
  176. package/dist/atoms/dialog.js +3 -2
  177. package/dist/atoms/ellipsis-tooltip.cjs +29 -2
  178. package/dist/atoms/ellipsis-tooltip.cjs.map +1 -1
  179. package/dist/atoms/ellipsis-tooltip.js +3 -2
  180. package/dist/atoms/field-error-wrapper.cjs +29 -2
  181. package/dist/atoms/field-error-wrapper.cjs.map +1 -1
  182. package/dist/atoms/field-error-wrapper.js +3 -2
  183. package/dist/atoms/heading.cjs +29 -2
  184. package/dist/atoms/heading.cjs.map +1 -1
  185. package/dist/atoms/heading.d.cts +2 -0
  186. package/dist/atoms/heading.d.ts +2 -0
  187. package/dist/atoms/heading.js +2 -1
  188. package/dist/atoms/index.cjs +49 -4
  189. package/dist/atoms/index.cjs.map +1 -1
  190. package/dist/atoms/index.js +67 -66
  191. package/dist/atoms/list.cjs +29 -2
  192. package/dist/atoms/list.cjs.map +1 -1
  193. package/dist/atoms/list.js +3 -2
  194. package/dist/atoms/pagination.cjs +29 -2
  195. package/dist/atoms/pagination.cjs.map +1 -1
  196. package/dist/atoms/pagination.js +3 -2
  197. package/dist/atoms/typo.cjs +29 -2
  198. package/dist/atoms/typo.cjs.map +1 -1
  199. package/dist/atoms/typo.d.cts +2 -0
  200. package/dist/atoms/typo.d.ts +2 -0
  201. package/dist/atoms/typo.js +2 -1
  202. package/dist/chunk-2TOASXPK.js +131 -0
  203. package/dist/chunk-2TOASXPK.js.map +1 -0
  204. package/dist/chunk-36W7VD2Z.js +13 -0
  205. package/dist/chunk-36W7VD2Z.js.map +1 -0
  206. package/dist/{chunk-7XMPNH2X.js → chunk-3DZIX4CE.js} +8 -8
  207. package/dist/chunk-3UGBMKSQ.js +166 -0
  208. package/dist/chunk-3UGBMKSQ.js.map +1 -0
  209. package/dist/{chunk-XFFVIWAD.js → chunk-47QYYEMG.js} +2 -2
  210. package/dist/{chunk-VVJEXKCB.js → chunk-4GH4R4VJ.js} +6 -6
  211. package/dist/chunk-4YAA25AV.js +161 -0
  212. package/dist/chunk-4YAA25AV.js.map +1 -0
  213. package/dist/{chunk-MTESLX7K.js → chunk-5IGBFB67.js} +12 -12
  214. package/dist/chunk-5QIT4URV.js +87 -0
  215. package/dist/chunk-5QIT4URV.js.map +1 -0
  216. package/dist/{chunk-LXL7GJUM.js → chunk-5RIAIE2J.js} +3 -3
  217. package/dist/{chunk-R43F6ZWT.js → chunk-64DSUMXA.js} +2 -2
  218. package/dist/{chunk-C2FRAZT2.js → chunk-6OT5OYGM.js} +2 -2
  219. package/dist/chunk-6YIKOYBQ.js +185 -0
  220. package/dist/chunk-6YIKOYBQ.js.map +1 -0
  221. package/dist/{chunk-6Q26H64H.js → chunk-74PR3ZWJ.js} +6 -6
  222. package/dist/{chunk-IA4WXGVH.js → chunk-75EY7LBP.js} +2 -2
  223. package/dist/chunk-7MXY3D3Z.js +84 -0
  224. package/dist/chunk-7MXY3D3Z.js.map +1 -0
  225. package/dist/{chunk-77YN5S26.js → chunk-AELKCD6B.js} +3 -3
  226. package/dist/{chunk-L5WSNVSD.js → chunk-AHYOAFOU.js} +3 -3
  227. package/dist/{chunk-6JPGF4MB.js → chunk-AT5PAJLW.js} +2 -2
  228. package/dist/{chunk-P6YCD2AV.js → chunk-C4INJWFV.js} +9 -9
  229. package/dist/{chunk-SGJBQKUD.js → chunk-C6HO3IGE.js} +2 -2
  230. package/dist/{chunk-7NBGSPZU.js → chunk-CBYIPRND.js} +5 -5
  231. package/dist/{chunk-UIMDXYPP.js → chunk-CGLDFUOY.js} +6 -6
  232. package/dist/{chunk-DUXYDGHX.js → chunk-CUS3ORMD.js} +6 -6
  233. package/dist/{chunk-UILGIMXL.js → chunk-D4U2ZV2A.js} +5 -5
  234. package/dist/{chunk-PRLNOTMV.js → chunk-DPMDQA3O.js} +6 -6
  235. package/dist/chunk-EBFQFOUQ.js +138 -0
  236. package/dist/chunk-EBFQFOUQ.js.map +1 -0
  237. package/dist/chunk-EHDUKUML.js +183 -0
  238. package/dist/chunk-EHDUKUML.js.map +1 -0
  239. package/dist/{chunk-6XASFDTI.js → chunk-EJXZXUD2.js} +15 -15
  240. package/dist/{chunk-QFSMOKC6.js → chunk-FAL6S2XK.js} +2 -2
  241. package/dist/{chunk-GMEGTXIV.js → chunk-FJEDSUGU.js} +5 -5
  242. package/dist/{chunk-WLG6GG26.js → chunk-G3KQN32M.js} +3 -3
  243. package/dist/chunk-GA6W62DO.js +101 -0
  244. package/dist/chunk-GA6W62DO.js.map +1 -0
  245. package/dist/{chunk-72ZC7DBY.js → chunk-GNB4A34H.js} +2 -2
  246. package/dist/{chunk-KEFAYPBO.js → chunk-IRFNKOKQ.js} +4 -4
  247. package/dist/{chunk-5BIICWFT.js → chunk-ISSUGCCY.js} +6 -6
  248. package/dist/{chunk-PZDN6K6R.js → chunk-JCZXPONS.js} +4 -4
  249. package/dist/{chunk-7TRT4QTP.js → chunk-K4RZTENM.js} +2 -2
  250. package/dist/{chunk-Z54XTEAF.js → chunk-KDS7OQOY.js} +2 -2
  251. package/dist/chunk-KJPBBBVK.js +142 -0
  252. package/dist/chunk-KJPBBBVK.js.map +1 -0
  253. package/dist/{chunk-YXFHD2PY.js → chunk-L4QQGIYQ.js} +24 -3
  254. package/dist/chunk-L4QQGIYQ.js.map +1 -0
  255. package/dist/{chunk-YCV3HR4J.js → chunk-LAGJDIVU.js} +2 -2
  256. package/dist/{chunk-3UJEOHQT.js → chunk-LK2H4QTJ.js} +6 -6
  257. package/dist/{chunk-UHAMISMF.js → chunk-LRNO4W2P.js} +4 -4
  258. package/dist/{chunk-5FLPPHUZ.js → chunk-MQKIIIBW.js} +2 -2
  259. package/dist/{chunk-6YPAN4D3.js → chunk-N242VJOP.js} +5 -5
  260. package/dist/{chunk-PWUCBBQP.js → chunk-N3FMP27I.js} +6 -6
  261. package/dist/{chunk-NIMF5FJI.js → chunk-NK6S7ZMB.js} +6 -6
  262. package/dist/chunk-NKW6BO5R.js +264 -0
  263. package/dist/chunk-NKW6BO5R.js.map +1 -0
  264. package/dist/{chunk-IIA2BVJI.js → chunk-NVRVOTWZ.js} +3 -3
  265. package/dist/{chunk-GTTZJ2Y7.js → chunk-O332K3SW.js} +4 -4
  266. package/dist/{chunk-LCR5R743.js → chunk-OOM522XP.js} +2 -2
  267. package/dist/{chunk-FIQJUO66.js → chunk-OPIVSYLN.js} +5 -5
  268. package/dist/{chunk-SQZVLRUH.js → chunk-OUDDTPEN.js} +5 -5
  269. package/dist/chunk-OUP3VFXG.js +1 -0
  270. package/dist/chunk-OUP3VFXG.js.map +1 -0
  271. package/dist/{chunk-URSBI6BQ.js → chunk-OW2QNTK3.js} +3 -3
  272. package/dist/{chunk-GBT2BBZS.js → chunk-P2H3VCIB.js} +3 -3
  273. package/dist/{chunk-TF3RLGKA.js → chunk-P4DJ5F6Z.js} +4 -4
  274. package/dist/{chunk-YWLFDIBP.js → chunk-PAUEQXYG.js} +2 -2
  275. package/dist/{chunk-XOCVP6IW.js → chunk-Q2FDF2AB.js} +8 -8
  276. package/dist/{chunk-VFWRW7TA.js → chunk-QLNAAZJX.js} +2 -2
  277. package/dist/{chunk-C5CEDLV6.js → chunk-QLOYGKKM.js} +2 -2
  278. package/dist/chunk-QMAINJ4G.js +190 -0
  279. package/dist/chunk-QMAINJ4G.js.map +1 -0
  280. package/dist/{chunk-DDYPJWZV.js → chunk-RBU2TRYY.js} +10 -10
  281. package/dist/{chunk-FFGGO6E4.js → chunk-RRC4WFG3.js} +2 -2
  282. package/dist/{chunk-5SXTL6NO.js → chunk-RWJUXAFY.js} +2 -2
  283. package/dist/{chunk-BZVA4RGI.js → chunk-S4MEMFKG.js} +2 -2
  284. package/dist/{chunk-PTUL6MDB.js → chunk-SINRU2A6.js} +2 -2
  285. package/dist/{chunk-UA2HDDD4.js → chunk-SOKGYD5B.js} +6 -6
  286. package/dist/{chunk-BZCUF5K6.js → chunk-SQ3FYBJT.js} +5 -5
  287. package/dist/chunk-T7LKMJVA.js +142 -0
  288. package/dist/chunk-T7LKMJVA.js.map +1 -0
  289. package/dist/chunk-TFJJKM3W.js +261 -0
  290. package/dist/chunk-TFJJKM3W.js.map +1 -0
  291. package/dist/{chunk-5FXPD4NE.js → chunk-U2EAXN3Y.js} +7 -7
  292. package/dist/{chunk-B7SKF5RD.js → chunk-U7HF53KK.js} +4 -4
  293. package/dist/{chunk-YIVIBIK2.js → chunk-USGOLLYO.js} +24 -3
  294. package/dist/chunk-USGOLLYO.js.map +1 -0
  295. package/dist/{chunk-Z2U2YQOG.js → chunk-USL6PICI.js} +2 -2
  296. package/dist/chunk-UXAEOCOH.js +150 -0
  297. package/dist/chunk-UXAEOCOH.js.map +1 -0
  298. package/dist/{chunk-DHP7LYK7.js → chunk-UXH2XIB2.js} +2 -2
  299. package/dist/{chunk-U5LZO2EI.js → chunk-V7KAHLW2.js} +6 -6
  300. package/dist/{chunk-VYUQXEXS.js → chunk-VBXZIIUA.js} +5 -5
  301. package/dist/{chunk-IYAN33WP.js → chunk-VVWQZK5L.js} +3 -3
  302. package/dist/{chunk-DBXQFZBB.js → chunk-WLKK5L3P.js} +8 -8
  303. package/dist/chunk-WTS75RUC.js +1 -0
  304. package/dist/chunk-WTS75RUC.js.map +1 -0
  305. package/dist/{chunk-ANFQJ6YW.js → chunk-WYHDQK2S.js} +9 -9
  306. package/dist/{chunk-RVHE3UVN.js → chunk-X3TBEGPA.js} +6 -6
  307. package/dist/chunk-XM4GWPXC.js +236 -0
  308. package/dist/chunk-XM4GWPXC.js.map +1 -0
  309. package/dist/{chunk-AEDSRBBB.js → chunk-XWHBJY5V.js} +3 -3
  310. package/dist/{chunk-SHFN2BOB.js → chunk-ZGTGEBQX.js} +2 -2
  311. package/dist/context/dynamic-form-context.cjs +49 -4
  312. package/dist/context/dynamic-form-context.cjs.map +1 -1
  313. package/dist/context/dynamic-form-context.js +5 -4
  314. package/dist/context/index.cjs +49 -4
  315. package/dist/context/index.cjs.map +1 -1
  316. package/dist/context/index.js +5 -4
  317. package/dist/index.cjs +51 -4
  318. package/dist/index.cjs.map +1 -1
  319. package/dist/index.css +76 -0
  320. package/dist/index.d.cts +1 -0
  321. package/dist/index.d.ts +1 -0
  322. package/dist/index.js +161 -157
  323. package/dist/molecules/autocomplete-textfield.cjs +29 -2
  324. package/dist/molecules/autocomplete-textfield.cjs.map +1 -1
  325. package/dist/molecules/autocomplete-textfield.js +3 -2
  326. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/index.cjs +49 -4
  327. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/index.cjs.map +1 -1
  328. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/index.js +14 -13
  329. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-comp.cjs +29 -2
  330. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-comp.cjs.map +1 -1
  331. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-comp.js +3 -2
  332. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-body.cjs +29 -2
  333. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-body.cjs.map +1 -1
  334. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-body.js +10 -9
  335. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-header.cjs +49 -4
  336. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-header.cjs.map +1 -1
  337. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-header.js +4 -3
  338. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-radio.cjs +29 -2
  339. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-radio.cjs.map +1 -1
  340. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-radio.js +5 -4
  341. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-satisfaction-option.cjs +29 -2
  342. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-satisfaction-option.cjs.map +1 -1
  343. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-satisfaction-option.js +5 -4
  344. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-satisfaction-text.cjs +29 -2
  345. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-satisfaction-text.cjs.map +1 -1
  346. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-satisfaction-text.js +5 -4
  347. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-text.cjs +29 -2
  348. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-text.cjs.map +1 -1
  349. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-text.js +6 -5
  350. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/complete-review.cjs +49 -4
  351. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/complete-review.cjs.map +1 -1
  352. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/complete-review.js +4 -3
  353. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/index.cjs +49 -4
  354. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/index.cjs.map +1 -1
  355. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/index.js +18 -17
  356. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/start-review.cjs +49 -4
  357. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/start-review.cjs.map +1 -1
  358. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/start-review.js +5 -4
  359. package/dist/molecules/curriculumV2/CurriculumContents/curriculum-ai-traning.cjs +29 -2
  360. package/dist/molecules/curriculumV2/CurriculumContents/curriculum-ai-traning.cjs.map +1 -1
  361. package/dist/molecules/curriculumV2/CurriculumContents/curriculum-ai-traning.js +3 -2
  362. package/dist/molecules/curriculumV2/CurriculumContents/curriculum-file-download.cjs +29 -2
  363. package/dist/molecules/curriculumV2/CurriculumContents/curriculum-file-download.cjs.map +1 -1
  364. package/dist/molecules/curriculumV2/CurriculumContents/curriculum-file-download.js +3 -2
  365. package/dist/molecules/curriculumV2/CurriculumContents/curriculum-review.cjs +49 -4
  366. package/dist/molecules/curriculumV2/CurriculumContents/curriculum-review.cjs.map +1 -1
  367. package/dist/molecules/curriculumV2/CurriculumContents/curriculum-review.js +20 -19
  368. package/dist/molecules/curriculumV2/CurriculumContents/index.cjs +49 -4
  369. package/dist/molecules/curriculumV2/CurriculumContents/index.cjs.map +1 -1
  370. package/dist/molecules/curriculumV2/CurriculumContents/index.js +23 -22
  371. package/dist/molecules/curriculumV2/CurriculumSidebar/Items/curriculum-item-title.cjs +29 -2
  372. package/dist/molecules/curriculumV2/CurriculumSidebar/Items/curriculum-item-title.cjs.map +1 -1
  373. package/dist/molecules/curriculumV2/CurriculumSidebar/Items/curriculum-item-title.js +3 -2
  374. package/dist/molecules/curriculumV2/CurriculumSidebar/Items/section-item.cjs +29 -2
  375. package/dist/molecules/curriculumV2/CurriculumSidebar/Items/section-item.cjs.map +1 -1
  376. package/dist/molecules/curriculumV2/CurriculumSidebar/Items/section-item.js +4 -3
  377. package/dist/molecules/curriculumV2/CurriculumSidebar/Items/section-title.cjs +29 -2
  378. package/dist/molecules/curriculumV2/CurriculumSidebar/Items/section-title.cjs.map +1 -1
  379. package/dist/molecules/curriculumV2/CurriculumSidebar/Items/section-title.js +3 -2
  380. package/dist/molecules/curriculumV2/CurriculumSidebar/index.cjs +29 -2
  381. package/dist/molecules/curriculumV2/CurriculumSidebar/index.cjs.map +1 -1
  382. package/dist/molecules/curriculumV2/CurriculumSidebar/index.js +8 -7
  383. package/dist/molecules/curriculumV2/CurriculumSidebar/sidebar-item.cjs +29 -2
  384. package/dist/molecules/curriculumV2/CurriculumSidebar/sidebar-item.cjs.map +1 -1
  385. package/dist/molecules/curriculumV2/CurriculumSidebar/sidebar-item.js +6 -5
  386. package/dist/molecules/curriculumV2/curriculum-sub-nav.cjs +49 -4
  387. package/dist/molecules/curriculumV2/curriculum-sub-nav.cjs.map +1 -1
  388. package/dist/molecules/curriculumV2/curriculum-sub-nav.js +4 -3
  389. package/dist/molecules/curriculumV2/index.cjs +49 -4
  390. package/dist/molecules/curriculumV2/index.cjs.map +1 -1
  391. package/dist/molecules/curriculumV2/index.js +33 -32
  392. package/dist/molecules/date-picker/date-picker-button.cjs +49 -4
  393. package/dist/molecules/date-picker/date-picker-button.cjs.map +1 -1
  394. package/dist/molecules/date-picker/date-picker-button.js +5 -4
  395. package/dist/molecules/date-picker/index.cjs +49 -4
  396. package/dist/molecules/date-picker/index.cjs.map +1 -1
  397. package/dist/molecules/date-picker/index.js +4 -3
  398. package/dist/molecules/description-json-render.cjs +29 -2
  399. package/dist/molecules/description-json-render.cjs.map +1 -1
  400. package/dist/molecules/description-json-render.js +5 -4
  401. package/dist/molecules/download-card.cjs +29 -2
  402. package/dist/molecules/download-card.cjs.map +1 -1
  403. package/dist/molecules/download-card.js +3 -2
  404. package/dist/molecules/dynamic-field.cjs +49 -4
  405. package/dist/molecules/dynamic-field.cjs.map +1 -1
  406. package/dist/molecules/dynamic-field.js +7 -6
  407. package/dist/molecules/dynamic-form-editor-field-editor-panel.cjs +29 -2
  408. package/dist/molecules/dynamic-form-editor-field-editor-panel.cjs.map +1 -1
  409. package/dist/molecules/dynamic-form-editor-field-editor-panel.js +5 -4
  410. package/dist/molecules/dynamic-form-editor-field-list-panel.cjs +29 -2
  411. package/dist/molecules/dynamic-form-editor-field-list-panel.cjs.map +1 -1
  412. package/dist/molecules/dynamic-form-editor-field-list-panel.js +4 -3
  413. package/dist/molecules/dynamic-form-editor-issues-panel.cjs +29 -2
  414. package/dist/molecules/dynamic-form-editor-issues-panel.cjs.map +1 -1
  415. package/dist/molecules/dynamic-form-editor-issues-panel.js +4 -3
  416. package/dist/molecules/dynamic-form-editor-preview-panel.cjs +49 -4
  417. package/dist/molecules/dynamic-form-editor-preview-panel.cjs.map +1 -1
  418. package/dist/molecules/dynamic-form-editor-preview-panel.js +10 -9
  419. package/dist/molecules/dynamic-form-editor.cjs +49 -4
  420. package/dist/molecules/dynamic-form-editor.cjs.map +1 -1
  421. package/dist/molecules/dynamic-form-editor.js +16 -15
  422. package/dist/molecules/dynamic-form.cjs +49 -4
  423. package/dist/molecules/dynamic-form.cjs.map +1 -1
  424. package/dist/molecules/dynamic-form.js +8 -7
  425. package/dist/molecules/expand-table/index.cjs +29 -2
  426. package/dist/molecules/expand-table/index.cjs.map +1 -1
  427. package/dist/molecules/expand-table/index.js +5 -4
  428. package/dist/molecules/force-refresh.cjs +29 -2
  429. package/dist/molecules/force-refresh.cjs.map +1 -1
  430. package/dist/molecules/force-refresh.js +3 -2
  431. package/dist/molecules/form/form.cjs +49 -4
  432. package/dist/molecules/form/form.cjs.map +1 -1
  433. package/dist/molecules/form/form.js +4 -3
  434. package/dist/molecules/form/index.cjs +49 -4
  435. package/dist/molecules/form/index.cjs.map +1 -1
  436. package/dist/molecules/form/index.js +4 -3
  437. package/dist/molecules/ghost-post.cjs +29 -2
  438. package/dist/molecules/ghost-post.cjs.map +1 -1
  439. package/dist/molecules/ghost-post.js +3 -2
  440. package/dist/molecules/index.cjs +49 -4
  441. package/dist/molecules/index.cjs.map +1 -1
  442. package/dist/molecules/index.js +76 -75
  443. package/dist/molecules/learning-post.cjs +49 -4
  444. package/dist/molecules/learning-post.cjs.map +1 -1
  445. package/dist/molecules/learning-post.js +6 -5
  446. package/dist/molecules/navigation.cjs +29 -2
  447. package/dist/molecules/navigation.cjs.map +1 -1
  448. package/dist/molecules/navigation.js +3 -2
  449. package/dist/molecules/one-on-one-guide-list.cjs +49 -4
  450. package/dist/molecules/one-on-one-guide-list.cjs.map +1 -1
  451. package/dist/molecules/one-on-one-guide-list.js +5 -4
  452. package/dist/molecules/stepper.cjs +29 -2
  453. package/dist/molecules/stepper.cjs.map +1 -1
  454. package/dist/molecules/stepper.js +4 -3
  455. package/dist/molecules/tag-selector.cjs +29 -2
  456. package/dist/molecules/tag-selector.cjs.map +1 -1
  457. package/dist/molecules/tag-selector.js +5 -4
  458. package/dist/molecules/time-select.js +3 -2
  459. package/dist/molecules/training-info-guideline.cjs +49 -4
  460. package/dist/molecules/training-info-guideline.cjs.map +1 -1
  461. package/dist/molecules/training-info-guideline.js +6 -5
  462. package/dist/utils/clamp-style.cjs +37 -0
  463. package/dist/utils/clamp-style.cjs.map +1 -0
  464. package/dist/utils/clamp-style.d.cts +13 -0
  465. package/dist/utils/clamp-style.d.ts +13 -0
  466. package/dist/utils/clamp-style.js +8 -0
  467. package/dist/utils/clamp-style.js.map +1 -0
  468. package/dist/utils/index.cjs +11 -0
  469. package/dist/utils/index.cjs.map +1 -1
  470. package/dist/utils/index.d.cts +1 -0
  471. package/dist/utils/index.d.ts +1 -0
  472. package/dist/utils/index.js +10 -6
  473. package/package.json +28 -2
  474. package/src/app/roleplay/chart/session-chart.tsx +185 -0
  475. package/src/app/roleplay/index.ts +8 -0
  476. package/src/app/roleplay/parts/analysis-section.tsx +98 -0
  477. package/src/app/roleplay/parts/coaching-panel.tsx +101 -0
  478. package/src/app/roleplay/parts/content.tsx +146 -0
  479. package/src/app/roleplay/parts/header.tsx +168 -0
  480. package/src/app/roleplay/parts/score-summary.tsx +158 -0
  481. package/src/app/roleplay/parts/score-trend-section.tsx +255 -0
  482. package/src/app/roleplay/parts/script-transcript.tsx +190 -0
  483. package/src/app/roleplay/parts/section-nav.tsx +299 -0
  484. package/src/app/roleplay/parts/session-replay-dialog.tsx +168 -0
  485. package/src/app/roleplay/parts/step-detail.tsx +173 -0
  486. package/src/app/roleplay/parts/step-radar.tsx +80 -0
  487. package/src/app/roleplay/parts/step-summary.tsx +149 -0
  488. package/src/app/roleplay/rp-session-detail.tsx +176 -0
  489. package/src/app/roleplay/types.ts +61 -0
  490. package/src/app/roleplay/utils/report-parse.test.ts +268 -0
  491. package/src/app/roleplay/utils/report-parse.ts +443 -0
  492. package/src/app/roleplay/utils/session-utils.ts +215 -0
  493. package/src/atoms/heading.tsx +19 -3
  494. package/src/atoms/typo.tsx +19 -3
  495. package/src/constrant/trainingLog.dummy.json +1 -0
  496. package/src/utils/clamp-style.ts +17 -0
  497. package/src/utils/index.ts +2 -1
  498. package/dist/chunk-U7PMCTVQ.js +0 -1
  499. package/dist/chunk-YIVIBIK2.js.map +0 -1
  500. package/dist/chunk-YXFHD2PY.js.map +0 -1
  501. /package/dist/{chunk-U7PMCTVQ.js.map → app/roleplay/chart/session-chart.js.map} +0 -0
  502. /package/dist/{chunk-7XMPNH2X.js.map → chunk-3DZIX4CE.js.map} +0 -0
  503. /package/dist/{chunk-XFFVIWAD.js.map → chunk-47QYYEMG.js.map} +0 -0
  504. /package/dist/{chunk-VVJEXKCB.js.map → chunk-4GH4R4VJ.js.map} +0 -0
  505. /package/dist/{chunk-MTESLX7K.js.map → chunk-5IGBFB67.js.map} +0 -0
  506. /package/dist/{chunk-LXL7GJUM.js.map → chunk-5RIAIE2J.js.map} +0 -0
  507. /package/dist/{chunk-R43F6ZWT.js.map → chunk-64DSUMXA.js.map} +0 -0
  508. /package/dist/{chunk-C2FRAZT2.js.map → chunk-6OT5OYGM.js.map} +0 -0
  509. /package/dist/{chunk-6Q26H64H.js.map → chunk-74PR3ZWJ.js.map} +0 -0
  510. /package/dist/{chunk-IA4WXGVH.js.map → chunk-75EY7LBP.js.map} +0 -0
  511. /package/dist/{chunk-77YN5S26.js.map → chunk-AELKCD6B.js.map} +0 -0
  512. /package/dist/{chunk-L5WSNVSD.js.map → chunk-AHYOAFOU.js.map} +0 -0
  513. /package/dist/{chunk-6JPGF4MB.js.map → chunk-AT5PAJLW.js.map} +0 -0
  514. /package/dist/{chunk-P6YCD2AV.js.map → chunk-C4INJWFV.js.map} +0 -0
  515. /package/dist/{chunk-SGJBQKUD.js.map → chunk-C6HO3IGE.js.map} +0 -0
  516. /package/dist/{chunk-7NBGSPZU.js.map → chunk-CBYIPRND.js.map} +0 -0
  517. /package/dist/{chunk-UIMDXYPP.js.map → chunk-CGLDFUOY.js.map} +0 -0
  518. /package/dist/{chunk-DUXYDGHX.js.map → chunk-CUS3ORMD.js.map} +0 -0
  519. /package/dist/{chunk-UILGIMXL.js.map → chunk-D4U2ZV2A.js.map} +0 -0
  520. /package/dist/{chunk-PRLNOTMV.js.map → chunk-DPMDQA3O.js.map} +0 -0
  521. /package/dist/{chunk-6XASFDTI.js.map → chunk-EJXZXUD2.js.map} +0 -0
  522. /package/dist/{chunk-QFSMOKC6.js.map → chunk-FAL6S2XK.js.map} +0 -0
  523. /package/dist/{chunk-GMEGTXIV.js.map → chunk-FJEDSUGU.js.map} +0 -0
  524. /package/dist/{chunk-WLG6GG26.js.map → chunk-G3KQN32M.js.map} +0 -0
  525. /package/dist/{chunk-72ZC7DBY.js.map → chunk-GNB4A34H.js.map} +0 -0
  526. /package/dist/{chunk-KEFAYPBO.js.map → chunk-IRFNKOKQ.js.map} +0 -0
  527. /package/dist/{chunk-5BIICWFT.js.map → chunk-ISSUGCCY.js.map} +0 -0
  528. /package/dist/{chunk-PZDN6K6R.js.map → chunk-JCZXPONS.js.map} +0 -0
  529. /package/dist/{chunk-7TRT4QTP.js.map → chunk-K4RZTENM.js.map} +0 -0
  530. /package/dist/{chunk-Z54XTEAF.js.map → chunk-KDS7OQOY.js.map} +0 -0
  531. /package/dist/{chunk-YCV3HR4J.js.map → chunk-LAGJDIVU.js.map} +0 -0
  532. /package/dist/{chunk-3UJEOHQT.js.map → chunk-LK2H4QTJ.js.map} +0 -0
  533. /package/dist/{chunk-UHAMISMF.js.map → chunk-LRNO4W2P.js.map} +0 -0
  534. /package/dist/{chunk-5FLPPHUZ.js.map → chunk-MQKIIIBW.js.map} +0 -0
  535. /package/dist/{chunk-6YPAN4D3.js.map → chunk-N242VJOP.js.map} +0 -0
  536. /package/dist/{chunk-PWUCBBQP.js.map → chunk-N3FMP27I.js.map} +0 -0
  537. /package/dist/{chunk-NIMF5FJI.js.map → chunk-NK6S7ZMB.js.map} +0 -0
  538. /package/dist/{chunk-IIA2BVJI.js.map → chunk-NVRVOTWZ.js.map} +0 -0
  539. /package/dist/{chunk-GTTZJ2Y7.js.map → chunk-O332K3SW.js.map} +0 -0
  540. /package/dist/{chunk-LCR5R743.js.map → chunk-OOM522XP.js.map} +0 -0
  541. /package/dist/{chunk-FIQJUO66.js.map → chunk-OPIVSYLN.js.map} +0 -0
  542. /package/dist/{chunk-SQZVLRUH.js.map → chunk-OUDDTPEN.js.map} +0 -0
  543. /package/dist/{chunk-URSBI6BQ.js.map → chunk-OW2QNTK3.js.map} +0 -0
  544. /package/dist/{chunk-GBT2BBZS.js.map → chunk-P2H3VCIB.js.map} +0 -0
  545. /package/dist/{chunk-TF3RLGKA.js.map → chunk-P4DJ5F6Z.js.map} +0 -0
  546. /package/dist/{chunk-YWLFDIBP.js.map → chunk-PAUEQXYG.js.map} +0 -0
  547. /package/dist/{chunk-XOCVP6IW.js.map → chunk-Q2FDF2AB.js.map} +0 -0
  548. /package/dist/{chunk-VFWRW7TA.js.map → chunk-QLNAAZJX.js.map} +0 -0
  549. /package/dist/{chunk-C5CEDLV6.js.map → chunk-QLOYGKKM.js.map} +0 -0
  550. /package/dist/{chunk-DDYPJWZV.js.map → chunk-RBU2TRYY.js.map} +0 -0
  551. /package/dist/{chunk-FFGGO6E4.js.map → chunk-RRC4WFG3.js.map} +0 -0
  552. /package/dist/{chunk-5SXTL6NO.js.map → chunk-RWJUXAFY.js.map} +0 -0
  553. /package/dist/{chunk-BZVA4RGI.js.map → chunk-S4MEMFKG.js.map} +0 -0
  554. /package/dist/{chunk-PTUL6MDB.js.map → chunk-SINRU2A6.js.map} +0 -0
  555. /package/dist/{chunk-UA2HDDD4.js.map → chunk-SOKGYD5B.js.map} +0 -0
  556. /package/dist/{chunk-BZCUF5K6.js.map → chunk-SQ3FYBJT.js.map} +0 -0
  557. /package/dist/{chunk-5FXPD4NE.js.map → chunk-U2EAXN3Y.js.map} +0 -0
  558. /package/dist/{chunk-B7SKF5RD.js.map → chunk-U7HF53KK.js.map} +0 -0
  559. /package/dist/{chunk-Z2U2YQOG.js.map → chunk-USL6PICI.js.map} +0 -0
  560. /package/dist/{chunk-DHP7LYK7.js.map → chunk-UXH2XIB2.js.map} +0 -0
  561. /package/dist/{chunk-U5LZO2EI.js.map → chunk-V7KAHLW2.js.map} +0 -0
  562. /package/dist/{chunk-VYUQXEXS.js.map → chunk-VBXZIIUA.js.map} +0 -0
  563. /package/dist/{chunk-IYAN33WP.js.map → chunk-VVWQZK5L.js.map} +0 -0
  564. /package/dist/{chunk-DBXQFZBB.js.map → chunk-WLKK5L3P.js.map} +0 -0
  565. /package/dist/{chunk-ANFQJ6YW.js.map → chunk-WYHDQK2S.js.map} +0 -0
  566. /package/dist/{chunk-RVHE3UVN.js.map → chunk-X3TBEGPA.js.map} +0 -0
  567. /package/dist/{chunk-AEDSRBBB.js.map → chunk-XWHBJY5V.js.map} +0 -0
  568. /package/dist/{chunk-SHFN2BOB.js.map → chunk-ZGTGEBQX.js.map} +0 -0
@@ -0,0 +1,443 @@
1
+ // 롤플레잉 평가 리포트(reportData) 제네릭 파서.
2
+ //
3
+ // 보고서 타입(reportType)은 계속 추가되며 그때마다 프론트를 수정할 수 없다.
4
+ // 따라서 프레임워크명 분기 없이 reportData 의 "키 패턴"만으로 해석한다.
5
+ //
6
+ // 입력 형태(프레임워크 공통, outputSchema 실측):
7
+ // reportData = { output_text: { todayDate, summary, {name}_items:[{...}], skills:[{...}],
8
+ // comprehensive_analysis? }, ai_traininglog_id }
9
+ // - {name}_items[0] 안에 모든 단계가 `${step}_score|_basis|_issue|_improve|_example|_quality` 평면 필드로 존재
10
+ // - 단계 라벨은 guideline.value[i].title (길이 일치 가드, 없으면 키 humanize 폴백)
11
+
12
+ /* ───────────────────────── 출력 타입 ───────────────────────── */
13
+
14
+ const QUALITIES = ['충족', '부분충족', '미흡'] as const;
15
+ export type RpQuality = (typeof QUALITIES)[number];
16
+
17
+ export interface RpReportStep {
18
+ key: string; // 단계 prefix (예: 'own', 'nurturing_org')
19
+ label: string; // displayMeta.steps.displayName → guideline 제목 → humanize 된 키
20
+ initial: string | null; // displayMeta.steps.initial. 없으면 null → session-utils stepCode 휴리스틱 폴백
21
+ description: string | null; // displayMeta.steps.description → guideline 단계 설명
22
+ idealExample: string | null; // guideline 모범 예시(있을 때)
23
+ score: number | null;
24
+ maxScore: number | null; // 신버전 리포트만 제공(구버전은 null) → 있으면 score/maxScore 표시
25
+ quality: RpQuality | null; // 표준 등급(충족/부분충족/미흡)일 때만. 색·정규화 비율 산출용
26
+ qualityLabel: string | null; // 원문 등급 문자열 그대로(예: 'X 매우 미흡'). 표시용
27
+ basis: string | null;
28
+ issue: string | null;
29
+ improve: string | null;
30
+ example: string | null; // reportData 의 단계별 예시 스크립트
31
+ }
32
+
33
+ export interface RpReportAnalysisItem {
34
+ title: string;
35
+ detail: string;
36
+ }
37
+
38
+ export interface RpReportSkill {
39
+ title: string;
40
+ description: string;
41
+ example: string;
42
+ }
43
+
44
+ export interface RpReport {
45
+ frameworkTitle: string | null; // displayMeta.title — 프레임워크 제목(지표와 별개). 없으면 null
46
+ frameworkDescription: string | null; // displayMeta.description — 프레임워크 설명문. 없으면 null
47
+ todayDate: string | null;
48
+ totalScore: number | null;
49
+ comment: string | null;
50
+ deduction: { score: number; basis: string } | null;
51
+ strengths: RpReportAnalysisItem[];
52
+ improvements: RpReportAnalysisItem[];
53
+ steps: RpReportStep[];
54
+ skills: RpReportSkill[];
55
+ }
56
+
57
+ /* ───────────────────────── displayMeta (framework 표시 메타) ───────────────────────── */
58
+
59
+ // framework.displayMeta = { title?, description?, steps:[{order,key,initial,displayName,maxValue,description}] }
60
+ // title/description은 프레임워크 자체(지표와 별개). steps는 지표별 표시 메타.
61
+ // 없거나 형식 불일치면 폴백(기존 동작).
62
+ export interface RpDisplayMetaStep {
63
+ order: number;
64
+ key: string; // = outputSchema {prefix}_score 의 prefix
65
+ initial: string;
66
+ displayName: string;
67
+ maxValue: number;
68
+ description: string;
69
+ }
70
+
71
+ export interface RpDisplayMeta {
72
+ title?: string;
73
+ description?: string;
74
+ steps: RpDisplayMetaStep[];
75
+ }
76
+
77
+ /* ───────────────────────── 원시 헬퍼 ───────────────────────── */
78
+
79
+ function isObject(v: unknown): v is Record<string, unknown> {
80
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
81
+ }
82
+
83
+ // Array.isArray 는 any[] 로 좁혀 unsafe 접근을 유발한다. unknown[] 로 좁히는 가드.
84
+ function isUnknownArray(v: unknown): v is unknown[] {
85
+ return Array.isArray(v);
86
+ }
87
+
88
+ function asString(v: unknown): string | null {
89
+ if (typeof v !== 'string') return null;
90
+ const t = v.trim();
91
+ return t.length > 0 ? t : null;
92
+ }
93
+
94
+ function asNumber(v: unknown): number | null {
95
+ return typeof v === 'number' && Number.isFinite(v) ? v : null;
96
+ }
97
+
98
+ function asQuality(v: unknown): RpQuality | null {
99
+ const t = asString(v);
100
+ if (t === null) return null;
101
+ return QUALITIES.find((q) => q === t) ?? null;
102
+ }
103
+
104
+ // guideline 의 example 은 string | string[] 모두 가능. '-' 플레이스홀더는 무시.
105
+ function asGuidelineText(v: unknown): string | null {
106
+ if (isUnknownArray(v)) {
107
+ const parts = v
108
+ .map(asString)
109
+ .filter((s): s is string => s !== null && s !== '-');
110
+ return parts.length > 0 ? parts.join('\n') : null;
111
+ }
112
+ const t = asString(v);
113
+ return t !== null && t !== '-' ? t : null;
114
+ }
115
+
116
+ function humanize(key: string): string {
117
+ return key
118
+ .split('_')
119
+ .filter((p) => p.length > 0)
120
+ .map((p) => p.charAt(0).toUpperCase() + p.slice(1))
121
+ .join(' ');
122
+ }
123
+
124
+ /* ───────────────────────── 단계 추출 ───────────────────────── */
125
+
126
+ // ⚠ 순서 중요: 더 긴/구체 suffix를 먼저 둬야 한다.
127
+ // 예) 'action_max_score' 는 '_score'보다 '_max_score' 가 먼저 매칭돼야
128
+ // prefix='action_max'(오인) 가 아니라 prefix='action', suffix='max_score' 로 잡힌다.
129
+ const STEP_SUFFIXES = [
130
+ 'max_score',
131
+ 'maxscore',
132
+ 'max',
133
+ 'score',
134
+ 'basis',
135
+ 'issue',
136
+ 'improve',
137
+ 'example',
138
+ 'quality',
139
+ ] as const;
140
+ type StepSuffix = (typeof STEP_SUFFIXES)[number];
141
+
142
+ function splitStepKey(
143
+ key: string
144
+ ): { prefix: string; suffix: StepSuffix } | null {
145
+ for (const suffix of STEP_SUFFIXES) {
146
+ const tail = `_${suffix}`;
147
+ if (key.endsWith(tail) && key.length > tail.length) {
148
+ return { prefix: key.slice(0, -tail.length), suffix };
149
+ }
150
+ }
151
+ return null;
152
+ }
153
+
154
+ interface GuidelineEntry {
155
+ title: string | null;
156
+ description: string | null;
157
+ example: string | null;
158
+ }
159
+
160
+ // guideline = { value: [{title, example, description}], version }. 미작성/길이불일치면 빈 배열 취급(=폴백).
161
+ function readGuidelineEntries(guideline: unknown): GuidelineEntry[] {
162
+ if (!isObject(guideline) || !isUnknownArray(guideline.value)) return [];
163
+ const entries: GuidelineEntry[] = guideline.value.map((v) => {
164
+ if (!isObject(v)) return { title: null, description: null, example: null };
165
+ const title = asString(v.title);
166
+ return {
167
+ title: title === '-' ? null : title,
168
+ description: asGuidelineText(v.description),
169
+ example: asGuidelineText(v.example),
170
+ };
171
+ });
172
+ // 전부 플레이스홀더면 라벨 소스로 쓰지 않는다.
173
+ if (entries.every((e) => e.title === null)) return [];
174
+ return entries;
175
+ }
176
+
177
+ // reportData item 객체에서 prefix→(suffix→값) 맵과 첫 등장 순서(order)를 만든다.
178
+ function buildFieldsMap(itemObj: Record<string, unknown>): {
179
+ order: string[];
180
+ fields: Map<string, Map<StepSuffix, unknown>>;
181
+ } {
182
+ const order: string[] = [];
183
+ const fields = new Map<string, Map<StepSuffix, unknown>>();
184
+
185
+ for (const [key, value] of Object.entries(itemObj)) {
186
+ const split = splitStepKey(key);
187
+ if (!split) continue;
188
+ if (!fields.has(split.prefix)) {
189
+ fields.set(split.prefix, new Map());
190
+ order.push(split.prefix);
191
+ }
192
+ fields.get(split.prefix)?.set(split.suffix, value);
193
+ }
194
+
195
+ return { order, fields };
196
+ }
197
+
198
+ // 단일 단계(step) 조립. 라벨/이니셜/설명/만점은 호출부(displayMeta 또는 폴백)가 결정해 주입.
199
+ function buildStep(
200
+ key: string,
201
+ f: Map<StepSuffix, unknown>,
202
+ meta: {
203
+ label: string;
204
+ initial: string | null;
205
+ description: string | null;
206
+ idealExample: string | null;
207
+ maxScoreFallback: number | null; // reportData 에 max 가 없을 때 쓸 만점(displayMeta.maxValue)
208
+ }
209
+ ): RpReportStep {
210
+ const qualityRaw = f.get('quality');
211
+ return {
212
+ key,
213
+ label: meta.label,
214
+ initial: meta.initial,
215
+ description: meta.description,
216
+ idealExample: meta.idealExample,
217
+ score: asNumber(f.get('score')),
218
+ // reportData 의 실제 만점이 우선, 없으면 displayMeta.maxValue 폴백.
219
+ maxScore:
220
+ asNumber(f.get('max_score') ?? f.get('maxscore') ?? f.get('max')) ??
221
+ meta.maxScoreFallback,
222
+ quality: asQuality(qualityRaw),
223
+ qualityLabel: asString(qualityRaw),
224
+ basis: asString(f.get('basis')),
225
+ issue: asString(f.get('issue')),
226
+ improve: asString(f.get('improve')),
227
+ example: asString(f.get('example')),
228
+ };
229
+ }
230
+
231
+ function extractSteps(
232
+ itemObj: Record<string, unknown>,
233
+ guideline: unknown,
234
+ displaySteps: RpDisplayMetaStep[]
235
+ ): RpReportStep[] {
236
+ const { order, fields } = buildFieldsMap(itemObj);
237
+ const entries = readGuidelineEntries(guideline);
238
+
239
+ // ── displayMeta.steps 우선: order 정렬된 steps 를 key 로 reportData 필드에 매칭.
240
+ if (displaySteps.length > 0) {
241
+ // guideline 의 단계 설명/모범예시 보강은 길이 일치 시에만 인덱스 매핑(기존 가드와 동일 정신).
242
+ const useGuideline = entries.length === displaySteps.length;
243
+ return displaySteps.map((ds, i) => {
244
+ const f = fields.get(ds.key) ?? new Map<StepSuffix, unknown>();
245
+ const entry = useGuideline ? entries[i] : null;
246
+ // 지표 설명: displayMeta.steps.description 우선, 없으면 guideline.
247
+ const dsDescription =
248
+ ds.description.trim().length > 0 ? ds.description : null;
249
+ return buildStep(ds.key, f, {
250
+ label: ds.displayName,
251
+ initial: ds.initial.trim().length > 0 ? ds.initial : null,
252
+ description: dsDescription ?? entry?.description ?? null,
253
+ idealExample: entry?.example ?? null,
254
+ maxScoreFallback: ds.maxValue > 0 ? ds.maxValue : null,
255
+ });
256
+ });
257
+ }
258
+
259
+ // ── 폴백: reportData 키 등장 순서 + guideline 길이일치 인덱스 매칭 + humanize.
260
+ const useGuideline = entries.length === order.length;
261
+ return order.map((prefix, i) => {
262
+ const f = fields.get(prefix) ?? new Map<StepSuffix, unknown>();
263
+ const entry = useGuideline ? entries[i] : null;
264
+ return buildStep(prefix, f, {
265
+ label: entry?.title ?? humanize(prefix),
266
+ initial: null,
267
+ description: entry?.description ?? null,
268
+ idealExample: entry?.example ?? null,
269
+ maxScoreFallback: null,
270
+ });
271
+ });
272
+ }
273
+
274
+ // framework.displayMeta(unknown) 를 견고하게 정규화.
275
+ // title/description(프레임워크 자체)과 steps(지표 배열)는 독립 — steps 가 비어도 title/description 은 살린다.
276
+ function readDisplayMeta(raw: unknown): {
277
+ title: string | null;
278
+ description: string | null;
279
+ steps: RpDisplayMetaStep[];
280
+ } {
281
+ if (!isObject(raw)) return { title: null, description: null, steps: [] };
282
+
283
+ const steps: RpDisplayMetaStep[] = [];
284
+ if (isUnknownArray(raw.steps)) {
285
+ for (const s of raw.steps) {
286
+ if (!isObject(s)) continue;
287
+ const key = asString(s.key);
288
+ if (key === null) continue; // key 없는 항목은 매칭 불가 → 제외
289
+ steps.push({
290
+ order: asNumber(s.order) ?? steps.length,
291
+ key,
292
+ initial: asString(s.initial) ?? '',
293
+ displayName: asString(s.displayName) ?? humanize(key),
294
+ maxValue: asNumber(s.maxValue) ?? 0,
295
+ description: asString(s.description) ?? '',
296
+ });
297
+ }
298
+ steps.sort((a, b) => a.order - b.order);
299
+ }
300
+
301
+ return {
302
+ title: asString(raw.title),
303
+ description: asString(raw.description),
304
+ steps,
305
+ };
306
+ }
307
+
308
+ /* ───────────────────────── 강점/개선점 (numbered-pair 평탄화) ───────────────────────── */
309
+
310
+ // 객체에서 `${titleBase}${n}` / `${detailBase}${n}` 쌍을 n=1.. 순으로 수집.
311
+ function flattenNumberedPairs(
312
+ obj: Record<string, unknown>,
313
+ titleBase: string,
314
+ detailBase: string
315
+ ): RpReportAnalysisItem[] {
316
+ const out: RpReportAnalysisItem[] = [];
317
+ for (let n = 1; ; n += 1) {
318
+ const title = asString(obj[`${titleBase}${n}`]);
319
+ if (title === null) break;
320
+ out.push({ title, detail: asString(obj[`${detailBase}${n}`]) ?? '' });
321
+ }
322
+ return out;
323
+ }
324
+
325
+ // 후보 (titleBase, detailBase) 쌍을 순서대로 시도, 첫 매치를 사용. (구·신 스키마 모두 대응)
326
+ const ANALYSIS_PAIR_CANDIDATES: readonly (readonly [string, string])[] = [
327
+ ['title', 'detail'],
328
+ ['improvement_title', 'improvement_action'],
329
+ ['issue_title', 'issue_detail'],
330
+ ];
331
+
332
+ function flattenAnalysis(source: unknown): RpReportAnalysisItem[] {
333
+ if (!isUnknownArray(source)) return [];
334
+ const out: RpReportAnalysisItem[] = [];
335
+ for (const obj of source) {
336
+ if (!isObject(obj)) continue;
337
+ for (const [titleBase, detailBase] of ANALYSIS_PAIR_CANDIDATES) {
338
+ const items = flattenNumberedPairs(obj, titleBase, detailBase);
339
+ if (items.length > 0) {
340
+ out.push(...items);
341
+ break;
342
+ }
343
+ }
344
+ }
345
+ return out;
346
+ }
347
+
348
+ /* ───────────────────────── skills 평탄화 ───────────────────────── */
349
+
350
+ function flattenSkills(source: unknown): RpReportSkill[] {
351
+ if (!isUnknownArray(source)) return [];
352
+ const out: RpReportSkill[] = [];
353
+ for (const obj of source) {
354
+ if (!isObject(obj)) continue;
355
+ for (let n = 1; ; n += 1) {
356
+ const title = asString(obj[`skill${n}`]);
357
+ if (title === null) break;
358
+ out.push({
359
+ title,
360
+ description: asString(obj[`description${n}`]) ?? '',
361
+ example: asString(obj[`example${n}`]) ?? '',
362
+ });
363
+ }
364
+ }
365
+ return out;
366
+ }
367
+
368
+ /* ───────────────────────── 종합/감점 ───────────────────────── */
369
+
370
+ function readDeduction(
371
+ summary: Record<string, unknown> | null
372
+ ): { score: number; basis: string } | null {
373
+ if (!summary || !isObject(summary.deduction)) return null;
374
+ const score = asNumber(summary.deduction.score);
375
+ const basis = asString(summary.deduction.basis);
376
+ if (score === null || basis === null) return null;
377
+ return { score, basis };
378
+ }
379
+
380
+ /* ───────────────────────── 메인 파서 ───────────────────────── */
381
+
382
+ // airflow 가 output_text 를 dict 로 정규화해 저장하므로(ai_traininglog_request_clova.py),
383
+ // 래퍼는 객체. 래퍼가 없으면(일부 프레임워크) reportData 자체를 루트로 사용.
384
+ function unwrapOutputText(reportData: unknown): Record<string, unknown> {
385
+ if (!isObject(reportData)) return {};
386
+ return isObject(reportData.output_text) ? reportData.output_text : reportData;
387
+ }
388
+
389
+ function findItemsArray(
390
+ root: Record<string, unknown>
391
+ ): Record<string, unknown> | null {
392
+ for (const [key, value] of Object.entries(root)) {
393
+ if (!key.endsWith('_items') || !isUnknownArray(value)) continue;
394
+ const first = value[0];
395
+ if (isObject(first)) return first;
396
+ }
397
+ return null;
398
+ }
399
+
400
+ export function parseReportData(
401
+ reportData: unknown,
402
+ guideline: unknown,
403
+ displayMeta?: unknown
404
+ ): RpReport {
405
+ const root = unwrapOutputText(reportData);
406
+ const meta = readDisplayMeta(displayMeta);
407
+
408
+ const summary = isObject(root.summary) ? root.summary : null;
409
+ const comprehensive = isObject(root.comprehensive_analysis)
410
+ ? root.comprehensive_analysis
411
+ : null;
412
+
413
+ // 종합 코멘트: 신(comprehensive_analysis) → 구(summary) 순.
414
+ const comment =
415
+ asString(comprehensive?.comment) ??
416
+ asString(summary?.comment) ??
417
+ asString(summary?.basis);
418
+
419
+ // 강점: comprehensive_analysis.strengths(신) → summary.good_point(구)
420
+ const strengths = flattenAnalysis(
421
+ comprehensive?.strengths ?? summary?.good_point
422
+ );
423
+ // 개선점: comprehensive_analysis.improvements(신) → summary.improvement(구)
424
+ const improvements = flattenAnalysis(
425
+ comprehensive?.improvements ?? summary?.improvement
426
+ );
427
+
428
+ const itemObj = findItemsArray(root);
429
+ const steps = itemObj ? extractSteps(itemObj, guideline, meta.steps) : [];
430
+
431
+ return {
432
+ frameworkTitle: meta.title,
433
+ frameworkDescription: meta.description,
434
+ todayDate: asString(root.todayDate),
435
+ totalScore: asNumber(summary?.total_score),
436
+ comment,
437
+ deduction: readDeduction(summary),
438
+ strengths,
439
+ improvements,
440
+ steps,
441
+ skills: flattenSkills(root.skills),
442
+ };
443
+ }
@@ -0,0 +1,215 @@
1
+ // 롤플레잉 세션 상세 순수 유틸 함수 모음.
2
+ // 원본: website/src/modules/customer/roleplay/pages/RpSessionDetail/RpSessionDetail.tsx
3
+ // 'use client' 없음 — 순수 함수, 클라이언트 전용 아님.
4
+
5
+ import { format } from 'date-fns';
6
+ import type { RpSessionScriptLine } from '../types';
7
+ import type { RpQuality, RpReportStep } from './report-parse';
8
+
9
+ /* ───────────────────────── 타입 ───────────────────────── */
10
+
11
+ export interface SpeechShare { userPct: number; partnerPct: number }
12
+
13
+ export type QColor = 'green' | 'amber' | 'red' | 'gray';
14
+
15
+ /* ───────────────────────── 색 변수 ───────────────────────── */
16
+
17
+ export const COLOR_VARS: Record<QColor, { fg: string; bg: string; border: string }> = {
18
+ green: {
19
+ fg: 'var(--green-11)',
20
+ bg: 'var(--green-a3)',
21
+ border: 'var(--green-a6)',
22
+ },
23
+ amber: {
24
+ fg: 'var(--amber-11)',
25
+ bg: 'var(--amber-a3)',
26
+ border: 'var(--amber-a6)',
27
+ },
28
+ red: { fg: 'var(--red-11)', bg: 'var(--red-a3)', border: 'var(--red-a6)' },
29
+ gray: { fg: 'var(--gray-9)', bg: 'var(--gray-a3)', border: 'var(--gray-5)' },
30
+ };
31
+
32
+ /* ───────────────────────── 등급 색 ───────────────────────── */
33
+
34
+ export function qualityColor(quality: RpQuality | null): QColor {
35
+ switch (quality) {
36
+ case '충족':
37
+ return 'green';
38
+ case '부분충족':
39
+ return 'amber';
40
+ case '미흡':
41
+ return 'red';
42
+ default:
43
+ return 'gray';
44
+ }
45
+ }
46
+
47
+ export const QUALITY_RATIO: Record<RpQuality, number> = {
48
+ 충족: 1,
49
+ 부분충족: 0.6,
50
+ 미흡: 0.3,
51
+ } as const;
52
+
53
+ export function qualityRatio(quality: RpQuality | null): number | null {
54
+ return quality === null ? null : QUALITY_RATIO[quality];
55
+ }
56
+
57
+ // 표준 등급이 아닌 자유 등급 문자열에서 색만 키워드로 추정(비율은 산출하지 않음).
58
+ export function gradeColorFromLabel(label: string | null): QColor {
59
+ if (!label) return 'gray';
60
+ if (
61
+ label.includes('미흡') ||
62
+ label.includes('부족') ||
63
+ label.includes('미달')
64
+ )
65
+ return 'red';
66
+ if (label.includes('부분') || label.includes('보통')) return 'amber';
67
+ if (
68
+ label.includes('충족') ||
69
+ label.includes('우수') ||
70
+ label.includes('충분')
71
+ )
72
+ return 'green';
73
+ return 'gray';
74
+ }
75
+
76
+ /* ───────────────────────── 단계(Step) 헬퍼 ───────────────────────── */
77
+
78
+ // 단계 색: 표준 등급 우선, 없으면 라벨 키워드 추정.
79
+ export function stepColor(step: RpReportStep): QColor {
80
+ return step.quality !== null
81
+ ? qualityColor(step.quality)
82
+ : gradeColorFromLabel(step.qualityLabel);
83
+ }
84
+
85
+ export function stepVars(step: RpReportStep): { fg: string; bg: string; border: string } {
86
+ return COLOR_VARS[stepColor(step)];
87
+ }
88
+
89
+ // progress/radar 정규화 비율(0~1). score/maxScore 우선, 없으면 표준 등급 비율, 둘 다 없으면 null.
90
+ export function stepRatio(step: RpReportStep): number | null {
91
+ if (step.maxScore !== null && step.maxScore > 0 && step.score !== null) {
92
+ return Math.max(0, Math.min(1, step.score / step.maxScore));
93
+ }
94
+ return qualityRatio(step.quality);
95
+ }
96
+
97
+ // 점수 텍스트: max 있으면 'score/max', 없으면 'score', score 없으면 null.
98
+ export function stepScoreText(step: RpReportStep): string | null {
99
+ if (step.score === null) return null;
100
+ return step.maxScore !== null
101
+ ? `${step.score}/${step.maxScore}`
102
+ : `${step.score}`;
103
+ }
104
+
105
+ // 표시할 등급 라벨(자유 문자열 포함). 없으면 null.
106
+ export function stepGradeLabel(step: RpReportStep): string | null {
107
+ return step.qualityLabel;
108
+ }
109
+
110
+ // 단계에 표시할 평가 정보가 하나라도 있는지(점수 또는 등급).
111
+ export function hasStepSignal(step: RpReportStep): boolean {
112
+ return step.score !== null || step.qualityLabel !== null;
113
+ }
114
+
115
+ // radar 축/요약 라벨용 짧은 코드.
116
+ // displayMeta.steps.initial 이 지정돼 있으면 최우선(이니셜 충돌 해소).
117
+ // 없으면 기존 휴리스틱: acronym 프레임워크는 선두 글자, 아니면 키 약식.
118
+ const LETTER_RE = /[A-Za-z]/;
119
+
120
+ export function stepCode(step: RpReportStep): string {
121
+ if (step.initial !== null && step.initial.trim().length > 0) {
122
+ return step.initial.trim();
123
+ }
124
+ const label = step.label.trim();
125
+ const first = label.charAt(0);
126
+ const second = label.charAt(1);
127
+ // "O — Opening" / "O - Opening" / "O Opening" 형태
128
+ if (
129
+ LETTER_RE.test(first) &&
130
+ (second === ' ' || second === '—' || second === '-')
131
+ ) {
132
+ return first.toUpperCase();
133
+ }
134
+ // "[I] Introduction" 형태
135
+ if (first === '[' && LETTER_RE.test(second) && label.charAt(2) === ']') {
136
+ return second.toUpperCase();
137
+ }
138
+ return step.key.split('_')[0].slice(0, 4).toUpperCase();
139
+ }
140
+
141
+ /* ───────────────────────── 포맷 유틸 ───────────────────────── */
142
+
143
+ export function formatDuration(seconds: number | null): string {
144
+ if (seconds === null) return '—';
145
+ const m = Math.floor(seconds / 60);
146
+ const s = seconds % 60;
147
+ return `${m}분 ${String(s).padStart(2, '0')}초`;
148
+ }
149
+
150
+ export function formatDate(iso: string): string {
151
+ const d = new Date(iso);
152
+ if (Number.isNaN(d.getTime())) return iso;
153
+ return format(d, 'M/d HH:mm');
154
+ }
155
+
156
+ export function formatTimestamp(ms: number): string {
157
+ const total = Math.floor(ms / 1000);
158
+ const m = Math.floor(total / 60);
159
+ const s = total % 60;
160
+ return `${m}:${String(s).padStart(2, '0')}`;
161
+ }
162
+
163
+ /* ───────────────────────── 미디어 싱크 ───────────────────────── */
164
+
165
+ // 미디어 길이와 STT 길이가 이 비율 이내로 가까우면 싱크(클릭 seek/재생 하이라이트) 활성.
166
+ export const SYNC_TOLERANCE = 0.05;
167
+
168
+ export function isLengthClose(mediaSec: number | null, sttSec: number): boolean {
169
+ if (!mediaSec || mediaSec <= 0 || sttSec <= 0) {
170
+ return false;
171
+ }
172
+ return (
173
+ Math.abs(mediaSec - sttSec) / Math.max(mediaSec, sttSec) <= SYNC_TOLERANCE
174
+ );
175
+ }
176
+
177
+ /* ───────────────────────── 발화량 ───────────────────────── */
178
+
179
+ // 내 발화량이 이 비율을 넘으면 과다 발화로 간주(빨간 막대 + 주의 문구).
180
+ export const SPEECH_OVERTALK_THRESHOLD = 40;
181
+
182
+ // 화자별 발화량 비율. 기준은 공백·개행 제거 글자 수(실제 말한 양에 근접, 공백 패턴 왜곡 방지).
183
+ // 발화 글자가 전혀 없으면 null → 미표시.
184
+ export function computeSpeechShare(lines: RpSessionScriptLine[]): SpeechShare | null {
185
+ let userChars = 0;
186
+ let partnerChars = 0;
187
+ for (const line of lines) {
188
+ const count = line.text.replace(/\s/g, '').length;
189
+ if (line.speaker === 'user') {
190
+ userChars += count;
191
+ } else {
192
+ partnerChars += count;
193
+ }
194
+ }
195
+ const total = userChars + partnerChars;
196
+ if (total === 0) {
197
+ return null;
198
+ }
199
+ const userPct = Math.round((userChars / total) * 100);
200
+ return { userPct, partnerPct: 100 - userPct };
201
+ }
202
+
203
+ /* ───────────────────────── 세션 상태 ───────────────────────── */
204
+
205
+ const STATUS_LABEL: Record<string, string> = {
206
+ complete: '분석 완료',
207
+ completed: '분석 완료',
208
+ analyzing: 'AI 분석 중',
209
+ partial: '일부 산출물 없음',
210
+ };
211
+
212
+ export function statusLabelOf(status: string | null): string {
213
+ if (!status) return '세션';
214
+ return STATUS_LABEL[status] ?? status;
215
+ }