analytica-frontend-lib 1.1.9 → 1.1.11

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.
package/dist/index.js CHANGED
@@ -6832,6 +6832,85 @@ var formatTime = (seconds) => {
6832
6832
  const secs = Math.floor(seconds % 60);
6833
6833
  return `${mins}:${secs.toString().padStart(2, "0")}`;
6834
6834
  };
6835
+ var ProgressBar2 = ({
6836
+ currentTime,
6837
+ duration,
6838
+ progressPercentage,
6839
+ onSeek
6840
+ }) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "px-4 pb-2", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6841
+ "input",
6842
+ {
6843
+ type: "range",
6844
+ min: 0,
6845
+ max: duration || 100,
6846
+ value: currentTime,
6847
+ onChange: (e) => onSeek(parseFloat(e.target.value)),
6848
+ className: "w-full h-1 bg-neutral-600 rounded-full appearance-none cursor-pointer slider:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-primary-500",
6849
+ "aria-label": "Video progress",
6850
+ style: {
6851
+ background: `linear-gradient(to right, var(--color-primary-700) ${progressPercentage}%, var(--color-secondary-300) ${progressPercentage}%)`
6852
+ }
6853
+ }
6854
+ ) });
6855
+ var VolumeControls = ({
6856
+ volume,
6857
+ isMuted,
6858
+ onVolumeChange,
6859
+ onToggleMute
6860
+ }) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-2", children: [
6861
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6862
+ IconButton_default,
6863
+ {
6864
+ icon: isMuted ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_phosphor_react18.SpeakerSlash, { size: 24 }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_phosphor_react18.SpeakerHigh, { size: 24 }),
6865
+ onClick: onToggleMute,
6866
+ "aria-label": isMuted ? "Unmute" : "Mute",
6867
+ className: "!bg-transparent !text-white hover:!bg-white/20"
6868
+ }
6869
+ ),
6870
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6871
+ "input",
6872
+ {
6873
+ type: "range",
6874
+ min: 0,
6875
+ max: 100,
6876
+ value: Math.round(volume * 100),
6877
+ onChange: (e) => onVolumeChange(parseInt(e.target.value)),
6878
+ className: "w-20 h-1 bg-neutral-600 rounded-full appearance-none cursor-pointer focus:outline-none focus:ring-2 focus:ring-primary-500",
6879
+ "aria-label": "Volume control",
6880
+ style: {
6881
+ background: `linear-gradient(to right, var(--color-primary-700) ${volume * 100}%, var(--color-secondary-300) ${volume * 100}%)`
6882
+ }
6883
+ }
6884
+ )
6885
+ ] });
6886
+ var SpeedMenu = ({
6887
+ showSpeedMenu,
6888
+ playbackRate,
6889
+ onToggleMenu,
6890
+ onSpeedChange
6891
+ }) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "relative", children: [
6892
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6893
+ IconButton_default,
6894
+ {
6895
+ icon: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_phosphor_react18.DotsThreeVertical, { size: 24 }),
6896
+ onClick: onToggleMenu,
6897
+ "aria-label": "Playback speed",
6898
+ className: "!bg-transparent !text-white hover:!bg-white/20"
6899
+ }
6900
+ ),
6901
+ showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "absolute bottom-12 right-0 bg-black/90 rounded-lg p-2 min-w-20", children: [0.5, 0.75, 1, 1.25, 1.5, 2].map((speed) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
6902
+ "button",
6903
+ {
6904
+ onClick: () => onSpeedChange(speed),
6905
+ className: `block w-full text-left px-3 py-1 text-sm rounded hover:bg-white/20 transition-colors ${playbackRate === speed ? "text-primary-400" : "text-white"}`,
6906
+ children: [
6907
+ speed,
6908
+ "x"
6909
+ ]
6910
+ },
6911
+ speed
6912
+ )) })
6913
+ ] });
6835
6914
  var VideoPlayer = ({
6836
6915
  src,
6837
6916
  poster,
@@ -6856,10 +6935,51 @@ var VideoPlayer = ({
6856
6935
  const [showControls, setShowControls] = (0, import_react22.useState)(true);
6857
6936
  const [hasCompleted, setHasCompleted] = (0, import_react22.useState)(false);
6858
6937
  const [showCaptions, setShowCaptions] = (0, import_react22.useState)(false);
6938
+ (0, import_react22.useEffect)(() => {
6939
+ setHasCompleted(false);
6940
+ }, [src]);
6859
6941
  const [playbackRate, setPlaybackRate] = (0, import_react22.useState)(1);
6860
6942
  const [showSpeedMenu, setShowSpeedMenu] = (0, import_react22.useState)(false);
6861
6943
  const lastSaveTimeRef = (0, import_react22.useRef)(0);
6862
6944
  const trackRef = (0, import_react22.useRef)(null);
6945
+ const controlsTimeoutRef = (0, import_react22.useRef)(null);
6946
+ const lastMousePositionRef = (0, import_react22.useRef)({ x: 0, y: 0 });
6947
+ const mouseMoveTimeoutRef = (0, import_react22.useRef)(null);
6948
+ const clearControlsTimeout = (0, import_react22.useCallback)(() => {
6949
+ if (controlsTimeoutRef.current) {
6950
+ clearTimeout(controlsTimeoutRef.current);
6951
+ controlsTimeoutRef.current = null;
6952
+ }
6953
+ }, []);
6954
+ const clearMouseMoveTimeout = (0, import_react22.useCallback)(() => {
6955
+ if (mouseMoveTimeoutRef.current) {
6956
+ clearTimeout(mouseMoveTimeoutRef.current);
6957
+ mouseMoveTimeoutRef.current = null;
6958
+ }
6959
+ }, []);
6960
+ const showControlsWithTimer = (0, import_react22.useCallback)(() => {
6961
+ setShowControls(true);
6962
+ clearControlsTimeout();
6963
+ if (isPlaying) {
6964
+ const timeout = isFullscreen ? 2e3 : 3e3;
6965
+ controlsTimeoutRef.current = window.setTimeout(() => {
6966
+ setShowControls(false);
6967
+ }, timeout);
6968
+ }
6969
+ }, [isPlaying, isFullscreen, clearControlsTimeout]);
6970
+ const handleMouseMove = (0, import_react22.useCallback)(
6971
+ (event) => {
6972
+ const currentX = event.clientX;
6973
+ const currentY = event.clientY;
6974
+ const lastPos = lastMousePositionRef.current;
6975
+ const hasMoved = Math.abs(currentX - lastPos.x) > 5 || Math.abs(currentY - lastPos.y) > 5;
6976
+ if (hasMoved) {
6977
+ lastMousePositionRef.current = { x: currentX, y: currentY };
6978
+ showControlsWithTimer();
6979
+ }
6980
+ },
6981
+ [showControlsWithTimer]
6982
+ );
6863
6983
  (0, import_react22.useEffect)(() => {
6864
6984
  if (videoRef.current) {
6865
6985
  videoRef.current.volume = volume;
@@ -6867,84 +6987,129 @@ var VideoPlayer = ({
6867
6987
  }
6868
6988
  }, [volume, isMuted]);
6869
6989
  (0, import_react22.useEffect)(() => {
6870
- if (!autoSave || !storageKey) return;
6871
- const raw = localStorage.getItem(`${storageKey}-${src}`);
6872
- const saved = raw !== null ? Number(raw) : NaN;
6873
- const hasValidSaved = Number.isFinite(saved) && saved >= 0;
6874
- const hasValidInitial = Number.isFinite(initialTime) && initialTime >= 0;
6875
- let start;
6876
- if (hasValidInitial) {
6877
- start = initialTime;
6878
- } else if (hasValidSaved) {
6879
- start = saved;
6990
+ const video = videoRef.current;
6991
+ if (!video) return;
6992
+ const onPlay = () => setIsPlaying(true);
6993
+ const onPause = () => setIsPlaying(false);
6994
+ const onEnded = () => setIsPlaying(false);
6995
+ video.addEventListener("play", onPlay);
6996
+ video.addEventListener("pause", onPause);
6997
+ video.addEventListener("ended", onEnded);
6998
+ return () => {
6999
+ video.removeEventListener("play", onPlay);
7000
+ video.removeEventListener("pause", onPause);
7001
+ video.removeEventListener("ended", onEnded);
7002
+ };
7003
+ }, []);
7004
+ (0, import_react22.useEffect)(() => {
7005
+ if (isPlaying) {
7006
+ showControlsWithTimer();
6880
7007
  } else {
6881
- start = void 0;
7008
+ clearControlsTimeout();
7009
+ setShowControls(true);
6882
7010
  }
7011
+ }, [isPlaying, showControlsWithTimer, clearControlsTimeout]);
7012
+ (0, import_react22.useEffect)(() => {
7013
+ const handleFullscreenChange = () => {
7014
+ const isCurrentlyFullscreen = !!document.fullscreenElement;
7015
+ setIsFullscreen(isCurrentlyFullscreen);
7016
+ if (isCurrentlyFullscreen) {
7017
+ showControlsWithTimer();
7018
+ }
7019
+ };
7020
+ document.addEventListener("fullscreenchange", handleFullscreenChange);
7021
+ return () => {
7022
+ document.removeEventListener("fullscreenchange", handleFullscreenChange);
7023
+ };
7024
+ }, [showControlsWithTimer]);
7025
+ const getInitialTime = (0, import_react22.useCallback)(() => {
7026
+ if (!autoSave || !storageKey) {
7027
+ return Number.isFinite(initialTime) && initialTime >= 0 ? initialTime : void 0;
7028
+ }
7029
+ const saved = Number(localStorage.getItem(`${storageKey}-${src}`) || NaN);
7030
+ const hasValidInitial = Number.isFinite(initialTime) && initialTime >= 0;
7031
+ const hasValidSaved = Number.isFinite(saved) && saved >= 0;
7032
+ if (hasValidInitial) return initialTime;
7033
+ if (hasValidSaved) return saved;
7034
+ return void 0;
7035
+ }, [autoSave, storageKey, src, initialTime]);
7036
+ (0, import_react22.useEffect)(() => {
7037
+ const start = getInitialTime();
6883
7038
  if (start !== void 0 && videoRef.current) {
6884
7039
  videoRef.current.currentTime = start;
6885
7040
  setCurrentTime(start);
6886
7041
  }
6887
- }, [src, storageKey, autoSave, initialTime]);
6888
- const saveProgress = (0, import_react22.useCallback)(() => {
6889
- if (!autoSave || !storageKey) return;
6890
- const now = Date.now();
6891
- if (now - lastSaveTimeRef.current > 5e3) {
6892
- localStorage.setItem(`${storageKey}-${src}`, currentTime.toString());
6893
- lastSaveTimeRef.current = now;
6894
- }
6895
- }, [autoSave, storageKey, src, currentTime]);
6896
- const togglePlayPause = (0, import_react22.useCallback)(() => {
6897
- if (videoRef.current) {
6898
- if (isPlaying) {
6899
- videoRef.current.pause();
6900
- } else {
6901
- videoRef.current.play();
7042
+ }, [getInitialTime]);
7043
+ const saveProgress = (0, import_react22.useCallback)(
7044
+ (time) => {
7045
+ if (!autoSave || !storageKey) return;
7046
+ const now = Date.now();
7047
+ if (now - lastSaveTimeRef.current > 5e3) {
7048
+ localStorage.setItem(`${storageKey}-${src}`, time.toString());
7049
+ lastSaveTimeRef.current = now;
6902
7050
  }
6903
- setIsPlaying(!isPlaying);
7051
+ },
7052
+ [autoSave, storageKey, src]
7053
+ );
7054
+ const togglePlayPause = (0, import_react22.useCallback)(async () => {
7055
+ const video = videoRef.current;
7056
+ if (!video) return;
7057
+ if (!video.paused) {
7058
+ video.pause();
7059
+ return;
6904
7060
  }
6905
- }, [isPlaying]);
7061
+ try {
7062
+ await video.play();
7063
+ } catch {
7064
+ }
7065
+ }, []);
6906
7066
  const handleVolumeChange = (0, import_react22.useCallback)(
6907
7067
  (newVolume) => {
6908
- if (videoRef.current) {
6909
- const volumeValue = newVolume / 100;
6910
- videoRef.current.volume = volumeValue;
6911
- setVolume(volumeValue);
6912
- if (volumeValue === 0) {
6913
- videoRef.current.muted = true;
6914
- setIsMuted(true);
6915
- } else if (isMuted) {
6916
- videoRef.current.muted = false;
6917
- setIsMuted(false);
6918
- }
7068
+ const video = videoRef.current;
7069
+ if (!video) return;
7070
+ const volumeValue = newVolume / 100;
7071
+ video.volume = volumeValue;
7072
+ setVolume(volumeValue);
7073
+ const shouldMute = volumeValue === 0;
7074
+ const shouldUnmute = volumeValue > 0 && isMuted;
7075
+ if (shouldMute) {
7076
+ video.muted = true;
7077
+ setIsMuted(true);
7078
+ } else if (shouldUnmute) {
7079
+ video.muted = false;
7080
+ setIsMuted(false);
6919
7081
  }
6920
7082
  },
6921
7083
  [isMuted]
6922
7084
  );
6923
7085
  const toggleMute = (0, import_react22.useCallback)(() => {
6924
- if (videoRef.current) {
6925
- if (isMuted) {
6926
- const restoreVolume = volume > 0 ? volume : 0.5;
6927
- videoRef.current.volume = restoreVolume;
6928
- videoRef.current.muted = false;
6929
- setVolume(restoreVolume);
6930
- setIsMuted(false);
6931
- } else {
6932
- videoRef.current.muted = true;
6933
- setIsMuted(true);
6934
- }
7086
+ const video = videoRef.current;
7087
+ if (!video) return;
7088
+ if (isMuted) {
7089
+ const restoreVolume = volume > 0 ? volume : 0.5;
7090
+ video.volume = restoreVolume;
7091
+ video.muted = false;
7092
+ setVolume(restoreVolume);
7093
+ setIsMuted(false);
7094
+ } else {
7095
+ video.muted = true;
7096
+ setIsMuted(true);
6935
7097
  }
6936
7098
  }, [isMuted, volume]);
7099
+ const handleSeek = (0, import_react22.useCallback)((newTime) => {
7100
+ const video = videoRef.current;
7101
+ if (video) {
7102
+ video.currentTime = newTime;
7103
+ }
7104
+ }, []);
6937
7105
  const toggleFullscreen = (0, import_react22.useCallback)(() => {
6938
7106
  const container = videoRef.current?.parentElement;
6939
7107
  if (!container) return;
6940
- if (!isFullscreen) {
6941
- if (container.requestFullscreen) {
6942
- container.requestFullscreen();
6943
- }
6944
- } else if (document.exitFullscreen) {
7108
+ if (!isFullscreen && container.requestFullscreen) {
7109
+ container.requestFullscreen();
7110
+ } else if (isFullscreen && document.exitFullscreen) {
6945
7111
  document.exitFullscreen();
6946
7112
  }
6947
- setIsFullscreen(!isFullscreen);
6948
7113
  }, [isFullscreen]);
6949
7114
  const handleSpeedChange = (0, import_react22.useCallback)((speed) => {
6950
7115
  if (videoRef.current) {
@@ -6957,39 +7122,43 @@ var VideoPlayer = ({
6957
7122
  setShowSpeedMenu(!showSpeedMenu);
6958
7123
  }, [showSpeedMenu]);
6959
7124
  const toggleCaptions = (0, import_react22.useCallback)(() => {
6960
- if (!trackRef.current?.track) return;
7125
+ if (!trackRef.current?.track || !subtitles) return;
6961
7126
  const newShowCaptions = !showCaptions;
6962
7127
  setShowCaptions(newShowCaptions);
6963
- trackRef.current.track.mode = newShowCaptions ? "showing" : "hidden";
6964
- }, [showCaptions]);
6965
- const handleTimeUpdate = (0, import_react22.useCallback)(() => {
6966
- if (videoRef.current) {
6967
- const current = videoRef.current.currentTime;
6968
- setCurrentTime(current);
6969
- saveProgress();
6970
- onTimeUpdate?.(current);
6971
- if (duration > 0) {
6972
- const progressPercent = current / duration * 100;
6973
- onProgress?.(progressPercent);
6974
- if (progressPercent >= 95 && !hasCompleted) {
6975
- setHasCompleted(true);
6976
- onVideoComplete?.();
6977
- }
7128
+ trackRef.current.track.mode = newShowCaptions && subtitles ? "showing" : "hidden";
7129
+ }, [showCaptions, subtitles]);
7130
+ const checkVideoCompletion = (0, import_react22.useCallback)(
7131
+ (progressPercent) => {
7132
+ if (progressPercent >= 95 && !hasCompleted) {
7133
+ setHasCompleted(true);
7134
+ onVideoComplete?.();
6978
7135
  }
7136
+ },
7137
+ [hasCompleted, onVideoComplete]
7138
+ );
7139
+ const handleTimeUpdate = (0, import_react22.useCallback)(() => {
7140
+ const video = videoRef.current;
7141
+ if (!video) return;
7142
+ const current = video.currentTime;
7143
+ setCurrentTime(current);
7144
+ saveProgress(current);
7145
+ onTimeUpdate?.(current);
7146
+ if (duration > 0) {
7147
+ const progressPercent = current / duration * 100;
7148
+ onProgress?.(progressPercent);
7149
+ checkVideoCompletion(progressPercent);
6979
7150
  }
6980
- }, [
6981
- duration,
6982
- saveProgress,
6983
- onTimeUpdate,
6984
- onProgress,
6985
- onVideoComplete,
6986
- hasCompleted
6987
- ]);
7151
+ }, [duration, saveProgress, onTimeUpdate, onProgress, checkVideoCompletion]);
6988
7152
  const handleLoadedMetadata = (0, import_react22.useCallback)(() => {
6989
7153
  if (videoRef.current) {
6990
7154
  setDuration(videoRef.current.duration);
6991
7155
  }
6992
7156
  }, []);
7157
+ (0, import_react22.useEffect)(() => {
7158
+ if (trackRef.current?.track) {
7159
+ trackRef.current.track.mode = showCaptions && subtitles ? "showing" : "hidden";
7160
+ }
7161
+ }, [subtitles, showCaptions]);
6993
7162
  (0, import_react22.useEffect)(() => {
6994
7163
  const handleVisibilityChange = () => {
6995
7164
  if (document.hidden && isPlaying && videoRef.current) {
@@ -7008,9 +7177,78 @@ var VideoPlayer = ({
7008
7177
  return () => {
7009
7178
  document.removeEventListener("visibilitychange", handleVisibilityChange);
7010
7179
  window.removeEventListener("blur", handleBlur);
7180
+ clearControlsTimeout();
7181
+ clearMouseMoveTimeout();
7011
7182
  };
7012
- }, [isPlaying]);
7183
+ }, [isPlaying, clearControlsTimeout, clearMouseMoveTimeout]);
7013
7184
  const progressPercentage = duration > 0 ? currentTime / duration * 100 : 0;
7185
+ const getTopControlsOpacity = (0, import_react22.useCallback)(() => {
7186
+ if (isFullscreen) {
7187
+ return showControls ? "opacity-100" : "opacity-0";
7188
+ }
7189
+ return !isPlaying || showControls ? "opacity-100" : "opacity-0 group-hover:opacity-100";
7190
+ }, [isFullscreen, showControls, isPlaying]);
7191
+ const getBottomControlsOpacity = (0, import_react22.useCallback)(() => {
7192
+ if (isFullscreen) {
7193
+ return showControls ? "opacity-100" : "opacity-0";
7194
+ }
7195
+ return !isPlaying || showControls ? "opacity-100" : "opacity-0 group-hover:opacity-100";
7196
+ }, [isFullscreen, showControls, isPlaying]);
7197
+ const handleVideoKeyDown = (0, import_react22.useCallback)(
7198
+ (e) => {
7199
+ if (e.key) {
7200
+ e.stopPropagation();
7201
+ showControlsWithTimer();
7202
+ }
7203
+ switch (e.key) {
7204
+ case " ":
7205
+ case "Enter":
7206
+ e.preventDefault();
7207
+ togglePlayPause();
7208
+ break;
7209
+ case "ArrowLeft":
7210
+ e.preventDefault();
7211
+ if (videoRef.current) {
7212
+ videoRef.current.currentTime -= 10;
7213
+ }
7214
+ break;
7215
+ case "ArrowRight":
7216
+ e.preventDefault();
7217
+ if (videoRef.current) {
7218
+ videoRef.current.currentTime += 10;
7219
+ }
7220
+ break;
7221
+ case "ArrowUp":
7222
+ e.preventDefault();
7223
+ handleVolumeChange(Math.min(100, volume * 100 + 10));
7224
+ break;
7225
+ case "ArrowDown":
7226
+ e.preventDefault();
7227
+ handleVolumeChange(Math.max(0, volume * 100 - 10));
7228
+ break;
7229
+ case "m":
7230
+ case "M":
7231
+ e.preventDefault();
7232
+ toggleMute();
7233
+ break;
7234
+ case "f":
7235
+ case "F":
7236
+ e.preventDefault();
7237
+ toggleFullscreen();
7238
+ break;
7239
+ default:
7240
+ break;
7241
+ }
7242
+ },
7243
+ [
7244
+ showControlsWithTimer,
7245
+ togglePlayPause,
7246
+ handleVolumeChange,
7247
+ volume,
7248
+ toggleMute,
7249
+ toggleFullscreen
7250
+ ]
7251
+ );
7014
7252
  return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: cn("flex flex-col", className), children: [
7015
7253
  (title || subtitleText) && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "bg-subject-1 rounded-t-xl px-8 py-4 flex items-end justify-between min-h-20", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-col gap-1", children: [
7016
7254
  title && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
@@ -7037,12 +7275,17 @@ var VideoPlayer = ({
7037
7275
  )
7038
7276
  ] }) }),
7039
7277
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7040
- "div",
7278
+ "section",
7041
7279
  {
7042
7280
  className: cn(
7043
7281
  "relative w-full bg-background overflow-hidden group",
7044
- title || subtitleText ? "rounded-b-xl" : "rounded-xl"
7282
+ title || subtitleText ? "rounded-b-xl" : "rounded-xl",
7283
+ // Hide cursor when controls are hidden and video is playing in fullscreen
7284
+ isFullscreen && isPlaying && !showControls ? "cursor-none" : "cursor-default"
7045
7285
  ),
7286
+ "aria-label": title ? `Video player: ${title}` : "Video player",
7287
+ onMouseMove: isFullscreen ? handleMouseMove : showControlsWithTimer,
7288
+ onMouseEnter: showControlsWithTimer,
7046
7289
  children: [
7047
7290
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7048
7291
  "video",
@@ -7055,39 +7298,7 @@ var VideoPlayer = ({
7055
7298
  onTimeUpdate: handleTimeUpdate,
7056
7299
  onLoadedMetadata: handleLoadedMetadata,
7057
7300
  onClick: togglePlayPause,
7058
- onKeyDown: (e) => {
7059
- if (e.key) {
7060
- setShowControls(true);
7061
- }
7062
- if (e.key === " " || e.key === "Enter") {
7063
- e.preventDefault();
7064
- togglePlayPause();
7065
- }
7066
- if (e.key === "ArrowLeft" && videoRef.current) {
7067
- e.preventDefault();
7068
- videoRef.current.currentTime -= 10;
7069
- }
7070
- if (e.key === "ArrowRight" && videoRef.current) {
7071
- e.preventDefault();
7072
- videoRef.current.currentTime += 10;
7073
- }
7074
- if (e.key === "ArrowUp") {
7075
- e.preventDefault();
7076
- handleVolumeChange(Math.min(100, volume * 100 + 10));
7077
- }
7078
- if (e.key === "ArrowDown") {
7079
- e.preventDefault();
7080
- handleVolumeChange(Math.max(0, volume * 100 - 10));
7081
- }
7082
- if (e.key === "m" || e.key === "M") {
7083
- e.preventDefault();
7084
- toggleMute();
7085
- }
7086
- if (e.key === "f" || e.key === "F") {
7087
- e.preventDefault();
7088
- toggleFullscreen();
7089
- }
7090
- },
7301
+ onKeyDown: handleVideoKeyDown,
7091
7302
  tabIndex: 0,
7092
7303
  "aria-label": title ? `Video: ${title}` : "Video player",
7093
7304
  children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
@@ -7095,9 +7306,9 @@ var VideoPlayer = ({
7095
7306
  {
7096
7307
  ref: trackRef,
7097
7308
  kind: "captions",
7098
- src: subtitles || "data:text/vtt;charset=utf-8,WEBVTT%0A%0ANOTE%20No%20captions%20available",
7099
- srcLang: "en",
7100
- label: subtitles ? "Subtitles" : "No captions available",
7309
+ src: subtitles || "data:text/vtt;charset=utf-8,WEBVTT",
7310
+ srcLang: "pt-br",
7311
+ label: subtitles ? "Legendas em Portugu\xEAs" : "Sem legendas dispon\xEDveis",
7101
7312
  default: false
7102
7313
  }
7103
7314
  )
@@ -7117,9 +7328,9 @@ var VideoPlayer = ({
7117
7328
  {
7118
7329
  className: cn(
7119
7330
  "absolute top-0 left-0 right-0 p-4 bg-gradient-to-b from-black/70 to-transparent transition-opacity",
7120
- !isPlaying || showControls ? "opacity-100" : "opacity-0 group-hover:opacity-100"
7331
+ getTopControlsOpacity()
7121
7332
  ),
7122
- children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "ml-auto block", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7333
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7123
7334
  IconButton_default,
7124
7335
  {
7125
7336
  icon: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_phosphor_react18.ArrowsInSimple, { size: 24 }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_phosphor_react18.ArrowsOutSimple, { size: 24 }),
@@ -7135,29 +7346,18 @@ var VideoPlayer = ({
7135
7346
  {
7136
7347
  className: cn(
7137
7348
  "absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/90 to-transparent transition-opacity",
7138
- !isPlaying || showControls ? "opacity-100" : "opacity-0 group-hover:opacity-100"
7349
+ getBottomControlsOpacity()
7139
7350
  ),
7140
7351
  children: [
7141
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "px-4 pb-2", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7142
- "input",
7352
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7353
+ ProgressBar2,
7143
7354
  {
7144
- type: "range",
7145
- min: 0,
7146
- max: duration || 100,
7147
- value: currentTime,
7148
- onChange: (e) => {
7149
- const newTime = parseFloat(e.target.value);
7150
- if (videoRef.current) {
7151
- videoRef.current.currentTime = newTime;
7152
- }
7153
- },
7154
- className: "w-full h-1 bg-neutral-600 rounded-full appearance-none cursor-pointer slider:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-primary-500",
7155
- "aria-label": "Video progress",
7156
- style: {
7157
- background: `linear-gradient(to right, #2271C4 ${progressPercentage}%, #D5D4D4 ${progressPercentage}%)`
7158
- }
7355
+ currentTime,
7356
+ duration,
7357
+ progressPercentage,
7358
+ onSeek: handleSeek
7159
7359
  }
7160
- ) }),
7360
+ ),
7161
7361
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center justify-between px-4 pb-4", children: [
7162
7362
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-4", children: [
7163
7363
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
@@ -7169,32 +7369,15 @@ var VideoPlayer = ({
7169
7369
  className: "!bg-transparent !text-white hover:!bg-white/20"
7170
7370
  }
7171
7371
  ),
7172
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-2", children: [
7173
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7174
- IconButton_default,
7175
- {
7176
- icon: isMuted ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_phosphor_react18.SpeakerSlash, { size: 24 }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_phosphor_react18.SpeakerHigh, { size: 24 }),
7177
- onClick: toggleMute,
7178
- "aria-label": isMuted ? "Unmute" : "Mute",
7179
- className: "!bg-transparent !text-white hover:!bg-white/20"
7180
- }
7181
- ),
7182
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7183
- "input",
7184
- {
7185
- type: "range",
7186
- min: 0,
7187
- max: 100,
7188
- value: Math.round(volume * 100),
7189
- onChange: (e) => handleVolumeChange(parseInt(e.target.value)),
7190
- className: "w-20 h-1 bg-neutral-600 rounded-full appearance-none cursor-pointer focus:outline-none focus:ring-2 focus:ring-primary-500",
7191
- "aria-label": "Volume control",
7192
- style: {
7193
- background: `linear-gradient(to right, #2271C4 ${volume * 100}%, #D5D4D4 ${volume * 100}%)`
7194
- }
7195
- }
7196
- )
7197
- ] }),
7372
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7373
+ VolumeControls,
7374
+ {
7375
+ volume,
7376
+ isMuted,
7377
+ onVolumeChange: handleVolumeChange,
7378
+ onToggleMute: toggleMute
7379
+ }
7380
+ ),
7198
7381
  subtitles && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7199
7382
  IconButton_default,
7200
7383
  {
@@ -7213,29 +7396,15 @@ var VideoPlayer = ({
7213
7396
  formatTime(duration)
7214
7397
  ] })
7215
7398
  ] }),
7216
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex items-center gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "relative", children: [
7217
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7218
- IconButton_default,
7219
- {
7220
- icon: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_phosphor_react18.DotsThreeVertical, { size: 24 }),
7221
- onClick: toggleSpeedMenu,
7222
- "aria-label": "Playback speed",
7223
- className: "!bg-transparent !text-white hover:!bg-white/20"
7224
- }
7225
- ),
7226
- showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "absolute bottom-12 right-0 bg-black/90 rounded-lg p-2 min-w-20", children: [0.5, 0.75, 1, 1.25, 1.5, 2].map((speed) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7227
- "button",
7228
- {
7229
- onClick: () => handleSpeedChange(speed),
7230
- className: `block w-full text-left px-3 py-1 text-sm rounded hover:bg-white/20 transition-colors ${playbackRate === speed ? "text-primary-400" : "text-white"}`,
7231
- children: [
7232
- speed,
7233
- "x"
7234
- ]
7235
- },
7236
- speed
7237
- )) })
7238
- ] }) })
7399
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex items-center gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7400
+ SpeedMenu,
7401
+ {
7402
+ showSpeedMenu,
7403
+ playbackRate,
7404
+ onToggleMenu: toggleSpeedMenu,
7405
+ onSpeedChange: handleSpeedChange
7406
+ }
7407
+ ) })
7239
7408
  ] })
7240
7409
  ]
7241
7410
  }
@@ -7717,6 +7886,8 @@ var useQuizStore = (0, import_zustand7.create)()(
7717
7886
  isFinished: false,
7718
7887
  userId: "",
7719
7888
  variant: "default",
7889
+ questionsResult: null,
7890
+ currentQuestionResult: null,
7720
7891
  // Setters
7721
7892
  setBySimulated: (simulado) => set({ bySimulated: simulado }),
7722
7893
  setByActivity: (atividade) => set({ byActivity: atividade }),
@@ -7725,6 +7896,7 @@ var useQuizStore = (0, import_zustand7.create)()(
7725
7896
  setUserAnswers: (userAnswers) => set({ userAnswers }),
7726
7897
  getUserId: () => get().userId,
7727
7898
  setVariant: (variant) => set({ variant }),
7899
+ setQuestionResult: (questionsResult) => set({ questionsResult }),
7728
7900
  // Navigation
7729
7901
  goToNextQuestion: () => {
7730
7902
  const { currentQuestionIndex, getTotalQuestions } = get();
@@ -7777,9 +7949,9 @@ var useQuizStore = (0, import_zustand7.create)()(
7777
7949
  questionId,
7778
7950
  activityId,
7779
7951
  userId,
7780
- answer: question.type === "DISSERTATIVA" /* DISSERTATIVA */ ? answerId : null,
7781
- optionId: question.type === "DISSERTATIVA" /* DISSERTATIVA */ ? null : answerId,
7782
- questionType: question.type,
7952
+ answer: question.questionType === "DISSERTATIVA" /* DISSERTATIVA */ ? answerId : null,
7953
+ optionId: question.questionType === "DISSERTATIVA" /* DISSERTATIVA */ ? null : answerId,
7954
+ questionType: question.questionType,
7783
7955
  answerStatus: "PENDENTE_AVALIACAO" /* PENDENTE_AVALIACAO */
7784
7956
  };
7785
7957
  let updatedUserAnswers;
@@ -7819,7 +7991,7 @@ var useQuizStore = (0, import_zustand7.create)()(
7819
7991
  // selectMultipleAnswer is for non-dissertative questions
7820
7992
  optionId: answerId,
7821
7993
  // selectMultipleAnswer should only set optionId
7822
- questionType: question.type,
7994
+ questionType: question.questionType,
7823
7995
  answerStatus: "PENDENTE_AVALIACAO" /* PENDENTE_AVALIACAO */
7824
7996
  })
7825
7997
  );
@@ -7846,7 +8018,7 @@ var useQuizStore = (0, import_zustand7.create)()(
7846
8018
  const question = activeQuiz.quiz.questions.find(
7847
8019
  (q) => q.id === questionId
7848
8020
  );
7849
- if (!question || question.type !== "DISSERTATIVA" /* DISSERTATIVA */) {
8021
+ if (!question || question.questionType !== "DISSERTATIVA" /* DISSERTATIVA */) {
7850
8022
  console.warn(
7851
8023
  "selectDissertativeAnswer called for non-dissertative question"
7852
8024
  );
@@ -7896,7 +8068,7 @@ var useQuizStore = (0, import_zustand7.create)()(
7896
8068
  userId,
7897
8069
  answer: null,
7898
8070
  optionId: null,
7899
- questionType: currentQuestion.type,
8071
+ questionType: currentQuestion.questionType,
7900
8072
  answerStatus: "PENDENTE_AVALIACAO" /* PENDENTE_AVALIACAO */
7901
8073
  };
7902
8074
  let updatedUserAnswers;
@@ -7932,9 +8104,9 @@ var useQuizStore = (0, import_zustand7.create)()(
7932
8104
  questionId,
7933
8105
  activityId,
7934
8106
  userId,
7935
- answer: question.type === "DISSERTATIVA" /* DISSERTATIVA */ ? answerId || null : null,
7936
- optionId: question.type !== "DISSERTATIVA" /* DISSERTATIVA */ ? answerId || null : null,
7937
- questionType: question.type,
8107
+ answer: question.questionType === "DISSERTATIVA" /* DISSERTATIVA */ ? answerId || null : null,
8108
+ optionId: question.questionType !== "DISSERTATIVA" /* DISSERTATIVA */ ? answerId || null : null,
8109
+ questionType: question.questionType,
7938
8110
  answerStatus: "PENDENTE_AVALIACAO" /* PENDENTE_AVALIACAO */
7939
8111
  };
7940
8112
  if (existingAnswerIndex !== -1) {
@@ -7962,7 +8134,10 @@ var useQuizStore = (0, import_zustand7.create)()(
7962
8134
  timeElapsed: 0,
7963
8135
  isStarted: false,
7964
8136
  isFinished: false,
7965
- userId: ""
8137
+ userId: "",
8138
+ variant: "default",
8139
+ questionsResult: null,
8140
+ currentQuestionResult: null
7966
8141
  });
7967
8142
  },
7968
8143
  // Timer
@@ -8164,6 +8339,31 @@ var useQuizStore = (0, import_zustand7.create)()(
8164
8339
  (q) => q.id === questionId
8165
8340
  );
8166
8341
  return questionIndex + 1;
8342
+ },
8343
+ // Question Result
8344
+ getQuestionResultByQuestionId: (questionId) => {
8345
+ const { questionsResult } = get();
8346
+ return questionsResult?.answers.find(
8347
+ (answer) => answer.questionId === questionId
8348
+ ) || null;
8349
+ },
8350
+ getQuestionResultStatistics: () => {
8351
+ const { questionsResult } = get();
8352
+ return questionsResult?.statistics || null;
8353
+ },
8354
+ getQuestionResult: () => {
8355
+ const { questionsResult } = get();
8356
+ return questionsResult;
8357
+ },
8358
+ setQuestionsResult: (questionsResult) => {
8359
+ set({ questionsResult });
8360
+ },
8361
+ setCurrentQuestionResult: (currentQuestionResult) => {
8362
+ set({ currentQuestionResult });
8363
+ },
8364
+ getCurrentQuestionResult: () => {
8365
+ const { currentQuestionResult } = get();
8366
+ return currentQuestionResult;
8167
8367
  }
8168
8368
  };
8169
8369
  },
@@ -8219,18 +8419,21 @@ var Quiz = (0, import_react27.forwardRef)(({ children, className, variant = "def
8219
8419
  });
8220
8420
  var QuizHeaderResult = (0, import_react27.forwardRef)(
8221
8421
  ({ className, ...props }, ref) => {
8222
- const { getAllCurrentAnswer } = useQuizStore();
8223
- const usersAnswer = getAllCurrentAnswer();
8422
+ const { getQuestionResultByQuestionId, getCurrentQuestion } = useQuizStore();
8224
8423
  const [isCorrect, setIsCorrect] = (0, import_react27.useState)(false);
8225
8424
  (0, import_react27.useEffect)(() => {
8226
- if (usersAnswer) {
8227
- setIsCorrect(
8228
- usersAnswer.length > 0 ? usersAnswer.map(
8229
- (answer) => answer.answerStatus === "RESPOSTA_CORRETA" /* RESPOSTA_CORRETA */
8230
- ).every(Boolean) : false
8231
- );
8425
+ const cq = getCurrentQuestion();
8426
+ if (!cq) {
8427
+ setIsCorrect(false);
8428
+ return;
8232
8429
  }
8233
- }, [usersAnswer]);
8430
+ const qr = getQuestionResultByQuestionId(cq.id);
8431
+ setIsCorrect(qr?.answerStatus === "RESPOSTA_CORRETA" /* RESPOSTA_CORRETA */);
8432
+ }, [
8433
+ getCurrentQuestion,
8434
+ getQuestionResultByQuestionId,
8435
+ getCurrentQuestion()?.id
8436
+ ]);
8234
8437
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8235
8438
  "div",
8236
8439
  {
@@ -8313,7 +8516,7 @@ var QuizContainer = (0, import_react27.forwardRef)(({ children, className, ...pr
8313
8516
  );
8314
8517
  });
8315
8518
  var QuizContent = (0, import_react27.forwardRef)(({ paddingBottom }) => {
8316
- const { getCurrentQuestion, variant } = useQuizStore();
8519
+ const { getCurrentQuestion } = useQuizStore();
8317
8520
  const currentQuestion = getCurrentQuestion();
8318
8521
  const questionComponents = {
8319
8522
  ["ALTERNATIVA" /* ALTERNATIVA */]: QuizAlternative,
@@ -8324,26 +8527,35 @@ var QuizContent = (0, import_react27.forwardRef)(({ paddingBottom }) => {
8324
8527
  ["PREENCHER" /* PREENCHER */]: QuizFill,
8325
8528
  ["IMAGEM" /* IMAGEM */]: QuizImageQuestion
8326
8529
  };
8327
- const QuestionComponent = currentQuestion ? questionComponents[currentQuestion.type] : null;
8328
- return QuestionComponent ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(QuestionComponent, { variant, paddingBottom }) : null;
8530
+ const QuestionComponent = currentQuestion ? questionComponents[currentQuestion.questionType] : null;
8531
+ return QuestionComponent ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(QuestionComponent, { paddingBottom }) : null;
8329
8532
  });
8330
- var QuizAlternative = ({
8331
- variant = "default",
8332
- paddingBottom
8333
- }) => {
8334
- const { getCurrentQuestion, selectAnswer, getCurrentAnswer } = useQuizStore();
8533
+ var QuizAlternative = ({ paddingBottom }) => {
8534
+ const {
8535
+ getCurrentQuestion,
8536
+ selectAnswer,
8537
+ getQuestionResultByQuestionId,
8538
+ getCurrentAnswer,
8539
+ variant
8540
+ } = useQuizStore();
8335
8541
  const currentQuestion = getCurrentQuestion();
8542
+ const currentQuestionResult = getQuestionResultByQuestionId(
8543
+ currentQuestion?.id || ""
8544
+ );
8336
8545
  const currentAnswer = getCurrentAnswer();
8337
8546
  const alternatives = currentQuestion?.options?.map((option) => {
8338
8547
  let status = "neutral" /* NEUTRAL */;
8339
8548
  if (variant === "result") {
8340
- const isCorrectOption = currentQuestion.options.find(
8341
- (op) => op.isCorrect
8549
+ const isCorrectOption = currentQuestion.correctOptionIds?.includes(
8550
+ option.id
8342
8551
  );
8343
- if (isCorrectOption?.id === option.id) {
8552
+ const isSelected = currentQuestionResult?.optionId === option.id;
8553
+ if (isCorrectOption) {
8344
8554
  status = "correct" /* CORRECT */;
8345
- } else if (currentAnswer?.optionId === option.id && option.id !== isCorrectOption?.id) {
8555
+ } else if (isSelected && !isCorrectOption) {
8346
8556
  status = "incorrect" /* INCORRECT */;
8557
+ } else {
8558
+ status = "neutral" /* NEUTRAL */;
8347
8559
  }
8348
8560
  }
8349
8561
  return {
@@ -8363,8 +8575,8 @@ var QuizAlternative = ({
8363
8575
  name: `question-${currentQuestion?.id || "1"}`,
8364
8576
  layout: "compact",
8365
8577
  alternatives,
8366
- value: currentAnswer?.optionId || "",
8367
- selectedValue: currentAnswer?.optionId || "",
8578
+ value: variant === "result" ? currentQuestionResult?.optionId || "" : currentAnswer?.optionId || "",
8579
+ selectedValue: variant === "result" ? currentQuestionResult?.optionId || "" : currentAnswer?.optionId || "",
8368
8580
  onValueChange: (value) => {
8369
8581
  if (currentQuestion) {
8370
8582
  selectAnswer(currentQuestion.id, value);
@@ -8375,13 +8587,19 @@ var QuizAlternative = ({
8375
8587
  ) }) })
8376
8588
  ] });
8377
8589
  };
8378
- var QuizMultipleChoice = ({
8379
- variant = "default",
8380
- paddingBottom
8381
- }) => {
8382
- const { getCurrentQuestion, selectMultipleAnswer, getAllCurrentAnswer } = useQuizStore();
8590
+ var QuizMultipleChoice = ({ paddingBottom }) => {
8591
+ const {
8592
+ getCurrentQuestion,
8593
+ selectMultipleAnswer,
8594
+ getAllCurrentAnswer,
8595
+ getQuestionResultByQuestionId,
8596
+ variant
8597
+ } = useQuizStore();
8383
8598
  const currentQuestion = getCurrentQuestion();
8384
8599
  const allCurrentAnswers = getAllCurrentAnswer();
8600
+ const currentQuestionResult = getQuestionResultByQuestionId(
8601
+ currentQuestion?.id || ""
8602
+ );
8385
8603
  const prevSelectedValuesRef = (0, import_react27.useRef)([]);
8386
8604
  const prevQuestionIdRef = (0, import_react27.useRef)("");
8387
8605
  const allCurrentAnswerIds = (0, import_react27.useMemo)(() => {
@@ -8403,8 +8621,16 @@ var QuizMultipleChoice = ({
8403
8621
  prevSelectedValuesRef.current = selectedValues;
8404
8622
  return selectedValues;
8405
8623
  }
8624
+ if (variant == "result" && currentQuestionResult?.options.length && currentQuestionResult?.options.length > 0) {
8625
+ return currentQuestionResult?.options.map((op) => op.id) || [];
8626
+ }
8406
8627
  return prevSelectedValuesRef.current;
8407
- }, [selectedValues, currentQuestion?.id]);
8628
+ }, [
8629
+ selectedValues,
8630
+ currentQuestion?.id,
8631
+ variant,
8632
+ currentQuestionResult?.optionId
8633
+ ]);
8408
8634
  const handleSelectedValues = (0, import_react27.useCallback)(
8409
8635
  (values) => {
8410
8636
  if (currentQuestion) {
@@ -8420,11 +8646,18 @@ var QuizMultipleChoice = ({
8420
8646
  const choices = currentQuestion?.options?.map((option) => {
8421
8647
  let status = "neutral" /* NEUTRAL */;
8422
8648
  if (variant === "result") {
8423
- const isAllCorrectOptionId = currentQuestion.options.filter((op) => op.isCorrect).map((op) => op.id);
8424
- if (isAllCorrectOptionId.includes(option.id)) {
8649
+ const isCorrectOption = currentQuestion.correctOptionIds?.includes(
8650
+ option.id
8651
+ );
8652
+ const isSelected = currentQuestionResult?.options.find(
8653
+ (op) => op.id === option.id
8654
+ );
8655
+ if (isCorrectOption) {
8425
8656
  status = "correct" /* CORRECT */;
8426
- } else if (allCurrentAnswerIds?.includes(option.id) && !isAllCorrectOptionId.includes(option.id)) {
8657
+ } else if (isSelected && !isCorrectOption) {
8427
8658
  status = "incorrect" /* INCORRECT */;
8659
+ } else {
8660
+ status = "neutral" /* NEUTRAL */;
8428
8661
  }
8429
8662
  }
8430
8663
  return {
@@ -8450,12 +8683,18 @@ var QuizMultipleChoice = ({
8450
8683
  ) }) })
8451
8684
  ] });
8452
8685
  };
8453
- var QuizDissertative = ({
8454
- variant = "default",
8455
- paddingBottom
8456
- }) => {
8457
- const { getCurrentQuestion, getCurrentAnswer, selectDissertativeAnswer } = useQuizStore();
8686
+ var QuizDissertative = ({ paddingBottom }) => {
8687
+ const {
8688
+ getCurrentQuestion,
8689
+ getCurrentAnswer,
8690
+ selectDissertativeAnswer,
8691
+ getQuestionResultByQuestionId,
8692
+ variant
8693
+ } = useQuizStore();
8458
8694
  const currentQuestion = getCurrentQuestion();
8695
+ const currentQuestionResult = getQuestionResultByQuestionId(
8696
+ currentQuestion?.id || ""
8697
+ );
8459
8698
  const currentAnswer = getCurrentAnswer();
8460
8699
  const textareaRef = (0, import_react27.useRef)(null);
8461
8700
  const handleAnswerChange = (value) => {
@@ -8479,6 +8718,7 @@ var QuizDissertative = ({
8479
8718
  if (!currentQuestion) {
8480
8719
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "space-y-4", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-text-600 text-md", children: "Nenhuma quest\xE3o dispon\xEDvel" }) });
8481
8720
  }
8721
+ const localAnswer = (variant == "result" ? currentQuestionResult?.answer : currentAnswer?.answer) || "";
8482
8722
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
8483
8723
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(QuizSubTitle, { subTitle: "Resposta" }),
8484
8724
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(QuizContainer, { className: cn(variant != "result" && paddingBottom), children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "space-y-4 max-h-[600px] overflow-y-auto", children: variant === "default" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "space-y-4", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
@@ -8486,22 +8726,20 @@ var QuizDissertative = ({
8486
8726
  {
8487
8727
  ref: textareaRef,
8488
8728
  placeholder: "Escreva sua resposta",
8489
- value: currentAnswer?.answer || "",
8729
+ value: localAnswer,
8490
8730
  onChange: (e) => handleAnswerChange(e.target.value),
8491
8731
  rows: 4,
8492
8732
  className: "min-h-[120px] max-h-[400px] resize-none overflow-y-auto"
8493
8733
  }
8494
- ) }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "space-y-4", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-text-600 text-md whitespace-pre-wrap", children: currentAnswer?.answer || "Nenhuma resposta fornecida" }) }) }) }),
8495
- variant === "result" && currentAnswer?.answerStatus == "RESPOSTA_INCORRETA" /* RESPOSTA_INCORRETA */ && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
8734
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "space-y-4", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-text-600 text-md whitespace-pre-wrap", children: localAnswer || "Nenhuma resposta fornecida" }) }) }) }),
8735
+ variant === "result" && currentQuestionResult?.answerStatus == "RESPOSTA_INCORRETA" /* RESPOSTA_INCORRETA */ && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
8496
8736
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(QuizSubTitle, { subTitle: "Observa\xE7\xE3o do professor" }),
8497
8737
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(QuizContainer, { className: cn("", paddingBottom), children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-text-600 text-md whitespace-pre-wrap", children: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, urna eu tincidunt consectetur, nisi nisl aliquam nunc, eget aliquam massa nisl quis neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Integer euismod, urna eu tincidunt consectetur, nisi nisl aliquam nunc, eget aliquam massa nisl quis neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Suspendisse potenti. Nullam ac urna eu felis dapibus condimentum sit amet a augue. Sed non neque elit. Sed ut imperdiet nisi. Proin condimentum fermentum nunc. Etiam pharetra, erat sed fermentum feugiat, velit mauris egestas quam, ut aliquam massa nisl quis neque. Suspendisse in orci enim. Mauris euismod, urna eu tincidunt consectetur, nisi nisl aliquam nunc, eget aliquam massa nisl quis neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Integer euismod, urna eu tincidunt consectetur, nisi nisl aliquam nunc, eget aliquam massa nisl quis neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Suspendisse potenti. Nullam ac urna eu felis dapibus condimentum sit amet a augue. Sed non neque elit. Sed ut imperdiet nisi. Proin condimentum fermentum nunc. Etiam pharetra, erat sed fermentum feugiat, velit mauris egestas quam, ut aliquam massa nisl quis neque. Suspendisse in orci enim. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Integer euismod, urna eu tincidunt consectetur, nisi nisl aliquam nunc, eget aliquam massa nisl quis neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Suspendisse potenti. Nullam ac urna eu felis dapibus condimentum sit amet a augue. Sed non neque elit. Sed ut imperdiet nisi. Proin condimentum fermentum nunc. Etiam pharetra, erat sed fermentum feugiat, velit mauris egestas quam, ut aliquam massa nisl quis neque. Suspendisse in orci enim." }) })
8498
8738
  ] })
8499
8739
  ] });
8500
8740
  };
8501
- var QuizTrueOrFalse = ({
8502
- variant = "default",
8503
- paddingBottom
8504
- }) => {
8741
+ var QuizTrueOrFalse = ({ paddingBottom }) => {
8742
+ const { variant } = useQuizStore();
8505
8743
  const options = [
8506
8744
  {
8507
8745
  label: "25 metros",
@@ -8561,10 +8799,8 @@ var QuizTrueOrFalse = ({
8561
8799
  }) }) })
8562
8800
  ] });
8563
8801
  };
8564
- var QuizConnectDots = ({
8565
- variant = "default",
8566
- paddingBottom
8567
- }) => {
8802
+ var QuizConnectDots = ({ paddingBottom }) => {
8803
+ const { variant } = useQuizStore();
8568
8804
  const dotsOptions = [
8569
8805
  { label: "Ra\xE7\xE3o" },
8570
8806
  { label: "Rato" },
@@ -8690,10 +8926,8 @@ var QuizConnectDots = ({
8690
8926
  }) }) })
8691
8927
  ] });
8692
8928
  };
8693
- var QuizFill = ({
8694
- variant = "default",
8695
- paddingBottom = "pb-[80px]"
8696
- }) => {
8929
+ var QuizFill = ({ paddingBottom = "pb-[80px]" }) => {
8930
+ const { variant } = useQuizStore();
8697
8931
  const options = [
8698
8932
  "ci\xEAncia",
8699
8933
  "disciplina",
@@ -8862,10 +9096,8 @@ var QuizFill = ({
8862
9096
  ] })
8863
9097
  ] });
8864
9098
  };
8865
- var QuizImageQuestion = ({
8866
- variant = "default",
8867
- paddingBottom
8868
- }) => {
9099
+ var QuizImageQuestion = ({ paddingBottom }) => {
9100
+ const { variant } = useQuizStore();
8869
9101
  const correctPositionRelative = { x: 0.48, y: 0.45 };
8870
9102
  const calculateCorrectRadiusRelative = () => {
8871
9103
  const circleWidthRelative = 0.15;
@@ -9083,7 +9315,6 @@ var QuizFooter = (0, import_react27.forwardRef)(
9083
9315
  }, ref) => {
9084
9316
  const {
9085
9317
  currentQuestionIndex,
9086
- getUserAnswers,
9087
9318
  getTotalQuestions,
9088
9319
  goToNextQuestion,
9089
9320
  goToPreviousQuestion,
@@ -9093,7 +9324,7 @@ var QuizFooter = (0, import_react27.forwardRef)(
9093
9324
  getCurrentQuestion,
9094
9325
  getQuestionStatusFromUserAnswers,
9095
9326
  variant,
9096
- getActiveQuiz
9327
+ getQuestionResultStatistics
9097
9328
  } = useQuizStore();
9098
9329
  const totalQuestions = getTotalQuestions();
9099
9330
  const isFirstQuestion = currentQuestionIndex === 0;
@@ -9107,7 +9338,6 @@ var QuizFooter = (0, import_react27.forwardRef)(
9107
9338
  const [modalResolutionOpen, setModalResolutionOpen] = (0, import_react27.useState)(false);
9108
9339
  const [filterType, setFilterType] = (0, import_react27.useState)("all");
9109
9340
  const unansweredQuestions = getUnansweredQuestionsFromUserAnswers();
9110
- const userAnswers = getUserAnswers();
9111
9341
  const allQuestions = getTotalQuestions();
9112
9342
  const handleFinishQuiz = async () => {
9113
9343
  if (unansweredQuestions.length > 0) {
@@ -9267,21 +9497,9 @@ var QuizFooter = (0, import_react27.forwardRef)(
9267
9497
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("p", { className: "text-text-500 font-sm", children: [
9268
9498
  "Voc\xEA acertou",
9269
9499
  " ",
9270
- (() => {
9271
- const activeQuiz = getActiveQuiz();
9272
- if (!activeQuiz) return 0;
9273
- return userAnswers.filter((answer) => {
9274
- const question = activeQuiz.quiz.questions.find(
9275
- (q) => q.id === answer.questionId
9276
- );
9277
- const isCorrectOption = question?.options.find(
9278
- (op) => op.isCorrect
9279
- );
9280
- return question && answer.optionId === isCorrectOption?.id;
9281
- }).length;
9282
- })(),
9500
+ getQuestionResultStatistics()?.correctAnswers ?? "--",
9501
+ " de",
9283
9502
  " ",
9284
- "de ",
9285
9503
  allQuestions,
9286
9504
  " quest\xF5es."
9287
9505
  ] })
@@ -9338,7 +9556,7 @@ var QuizFooter = (0, import_react27.forwardRef)(
9338
9556
  onClose: () => setModalResolutionOpen(false),
9339
9557
  title: "Resolu\xE7\xE3o",
9340
9558
  size: "lg",
9341
- children: currentQuestion?.answerKey
9559
+ children: currentQuestion?.solutionExplanation
9342
9560
  }
9343
9561
  )
9344
9562
  ] });
@@ -9354,7 +9572,7 @@ var QuizResultHeaderTitle = (0, import_react27.forwardRef)(({ className, ...prop
9354
9572
  ...props,
9355
9573
  children: [
9356
9574
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-text-950 font-bold text-2xl", children: "Resultado" }),
9357
- bySimulated && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "solid", action: "info", children: bySimulated.category })
9575
+ bySimulated && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "solid", action: "info", children: bySimulated.type })
9358
9576
  ]
9359
9577
  }
9360
9578
  );
@@ -9378,13 +9596,11 @@ var QuizResultPerformance = (0, import_react27.forwardRef)(
9378
9596
  getTotalQuestions,
9379
9597
  timeElapsed,
9380
9598
  formatTime: formatTime2,
9381
- bySimulated,
9382
- byActivity,
9383
- byQuestionary,
9384
- getUserAnswerByQuestionId
9599
+ getQuestionResultStatistics,
9600
+ getQuestionResult
9385
9601
  } = useQuizStore();
9386
9602
  const totalQuestions = getTotalQuestions();
9387
- const quiz = bySimulated || byActivity || byQuestionary;
9603
+ const questionResult = getQuestionResult();
9388
9604
  let correctAnswers = 0;
9389
9605
  let correctEasyAnswers = 0;
9390
9606
  let correctMediumAnswers = 0;
@@ -9392,24 +9608,23 @@ var QuizResultPerformance = (0, import_react27.forwardRef)(
9392
9608
  let totalEasyQuestions = 0;
9393
9609
  let totalMediumQuestions = 0;
9394
9610
  let totalDifficultQuestions = 0;
9395
- if (quiz) {
9396
- quiz.questions.forEach((question) => {
9397
- const userAnswerItem = getUserAnswerByQuestionId(question.id);
9398
- const isCorrect = userAnswerItem?.answerStatus == "RESPOSTA_CORRETA" /* RESPOSTA_CORRETA */;
9611
+ if (questionResult) {
9612
+ questionResult.answers.forEach((answer) => {
9613
+ const isCorrect = answer.answerStatus == "RESPOSTA_CORRETA" /* RESPOSTA_CORRETA */;
9399
9614
  if (isCorrect) {
9400
9615
  correctAnswers++;
9401
9616
  }
9402
- if (question.difficulty === "FACIL" /* FACIL */) {
9617
+ if (answer.difficultyLevel === "FACIL" /* FACIL */) {
9403
9618
  totalEasyQuestions++;
9404
9619
  if (isCorrect) {
9405
9620
  correctEasyAnswers++;
9406
9621
  }
9407
- } else if (question.difficulty === "MEDIO" /* MEDIO */) {
9622
+ } else if (answer.difficultyLevel === "MEDIO" /* MEDIO */) {
9408
9623
  totalMediumQuestions++;
9409
9624
  if (isCorrect) {
9410
9625
  correctMediumAnswers++;
9411
9626
  }
9412
- } else if (question.difficulty === "DIFICIL" /* DIFICIL */) {
9627
+ } else if (answer.difficultyLevel === "DIFICIL" /* DIFICIL */) {
9413
9628
  totalDifficultQuestions++;
9414
9629
  if (isCorrect) {
9415
9630
  correctDifficultAnswers++;
@@ -9442,8 +9657,9 @@ var QuizResultPerformance = (0, import_react27.forwardRef)(
9442
9657
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-2xs font-medium text-text-800", children: formatTime2(timeElapsed) })
9443
9658
  ] }),
9444
9659
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "text-2xl font-medium text-text-800 leading-7", children: [
9445
- correctAnswers,
9446
- " de ",
9660
+ getQuestionResultStatistics()?.correctAnswers ?? "--",
9661
+ " de",
9662
+ " ",
9447
9663
  totalQuestions
9448
9664
  ] }),
9449
9665
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "text-2xs font-medium text-text-600 mt-1", children: "Corretas" })