chore(capacitor): refactor codebase for capacitor entry

This commit is contained in:
shafin-r
2025-09-08 13:42:15 +06:00
parent 3b2488054c
commit 99d6c15e38
21 changed files with 123 additions and 491 deletions

View File

@ -1,18 +1,38 @@
import React, { JSX } from "react";
interface DestructibleAlertProps {
variant?: "error" | "warning" | "alert";
text: string;
icon?: JSX.Element;
}
const DestructibleAlert: React.FC<DestructibleAlertProps> = ({
variant,
text,
icon,
}) => {
return (
<div className=" bg-red-200 rounded-3xl py-6 flex flex-col items-center justify-center gap-2 w-full ">
<div
className={`${
variant === "error"
? "bg-red-200"
: variant === "warning"
? "bg-yellow-200"
: "bg-green-200"
} rounded-3xl py-6 flex flex-col items-center justify-center gap-2 w-full `}
>
<div>{icon}</div>
<p className="text-lg font-bold text-center text-red-800">{text}</p>
<p
className={`text-lg font-bold text-center ${
variant === "error"
? "text-red-800"
: variant === "warning"
? "text-yellow-800"
: "text-green-800"
}`}
>
{text}
</p>
</div>
);
};

View File

@ -2,13 +2,10 @@
import React from "react";
import { useRouter } from "next/navigation";
import { ChevronLeft, Layers, Loader } from "lucide-react";
import { useTimer } from "@/context/TimerContext";
import { ChevronLeft, Layers } from "lucide-react";
import styles from "@/css/Header.module.css";
import { useExam } from "@/context/ExamContext";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { useModal } from "@/context/ModalContext";
import { useAuth } from "@/context/AuthContext";
import { useAuthStore } from "@/stores/authStore";
import { useTimerStore } from "@/stores/timerStore";
import { useExamStore } from "@/stores/examStore";

View File

@ -9,9 +9,9 @@ interface QuestionItemProps {
index: number;
selectedAnswer: Answer;
onSelect: (answer: Answer) => void;
userAnswer?: Answer; // new
correctAnswer?: Answer; // new
showResults?: boolean; // control whether to highlight or not
userAnswer?: Answer;
correctAnswer?: Answer;
showResults?: boolean;
}
const letters = ["A", "B", "C", "D"]; // extend if needed
@ -40,39 +40,20 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
<div className="flex flex-col gap-3">
{question.options.map((opt, optIdx) => {
const isSelected =
question.type === "Single"
? selectedAnswer === optIdx
: Array.isArray(selectedAnswer) &&
selectedAnswer.includes(optIdx);
const isSelected = selectedAnswer === optIdx;
// ✅ logic for coloring after results
// ✅ logic for coloring
let btnClasses = "bg-gray-100 text-gray-900 border-gray-400";
if (isSelected) {
btnClasses = "bg-blue-600 text-white border-blue-600";
}
if (showResults && correctAnswer !== undefined) {
if (question.type === "Single") {
if (userAnswer === optIdx && userAnswer !== correctAnswer) {
btnClasses = "bg-red-500 text-white border-red-600"; // wrong
}
if (correctAnswer === optIdx) {
btnClasses = "bg-green-500 text-white border-green-600"; // correct
}
} else {
// Multi-select case
const userSelected =
Array.isArray(userAnswer) && userAnswer.includes(optIdx);
const isCorrect =
Array.isArray(correctAnswer) && correctAnswer.includes(optIdx);
if (userSelected && !isCorrect) {
btnClasses = "bg-red-500 text-white border-red-600";
}
if (isCorrect) {
btnClasses = "bg-green-500 text-white border-green-600";
}
if (userAnswer === optIdx && userAnswer !== correctAnswer) {
btnClasses = "bg-red-500 text-white border-red-600"; // wrong
}
if (correctAnswer === optIdx) {
btnClasses = "bg-green-500 text-white border-green-600"; // correct
}
}
@ -80,20 +61,8 @@ const QuestionItem: React.FC<QuestionItemProps> = ({
<div key={optIdx} className="flex items-center gap-3">
<button
onClick={() => {
if (showResults) return; // disable changes in results mode
if (question.type === "Single") {
onSelect(optIdx);
} else {
let newAnswers = Array.isArray(selectedAnswer)
? [...selectedAnswer]
: [];
if (newAnswers.includes(optIdx)) {
newAnswers = newAnswers.filter((a) => a !== optIdx);
} else {
newAnswers.push(optIdx);
}
onSelect(newAnswers);
}
if (showResults) return; // disable selection in results mode
onSelect(optIdx); // always a number
}}
className={`w-7 h-7 rounded-full border font-bold
flex items-center justify-center

View File

@ -5,7 +5,6 @@ import React, {
useCallback,
UIEvent,
} from "react";
import styles from "../css/SlidingGallery.module.css";
import { GalleryViews } from "@/types/gallery";
interface SlidingGalleryProps {
@ -120,8 +119,10 @@ const SlidingGallery = ({
if (!views || views.length === 0) {
return (
<div className={`${styles.gallery} ${className}`}>
<div className={styles.emptyState}>
<div
className={`relative w-full h-screen overflow-hidden flex flex-col ${className}`}
>
<div className="flex-1 flex items-center justify-center text-slate-400 text-lg">
<p>No content to display</p>
</div>
</div>
@ -130,12 +131,12 @@ const SlidingGallery = ({
return (
<div
className={`${styles.gallery} ${className}`}
className={`relative w-full h-screen overflow-hidden flex flex-col ${className}`}
ref={galleryRef}
style={{ height }}
>
<div
className={styles.scrollContainer}
className="flex-1 flex overflow-x-auto"
ref={scrollRef}
onScroll={handleScroll}
style={{
@ -143,16 +144,20 @@ const SlidingGallery = ({
height: "100%",
overflowX: "scroll",
display: "flex",
scrollSnapType: "x mandatory",
scrollbarWidth: "none",
msOverflowStyle: "none",
}}
>
{views.map((item) => (
<div
key={item.id}
className={styles.slide}
className="min-w-full flex items-center justify-center px-2 box-border"
style={{
width: dimensions.width,
height: "100%",
flexShrink: 0,
scrollSnapAlign: "start",
}}
>
{item.content}
@ -161,15 +166,14 @@ const SlidingGallery = ({
</div>
{showPagination && views.length > 1 && (
<div className={styles.pagination}>
<div className="absolute bottom-[15px] left-1/2 -translate-x-1/2 flex gap-1.5 z-10">
{views.map((_, index) => (
<div
key={index}
className={`${styles.dot} ${
activeIdx === index ? styles.activeDot : styles.inactiveDot
className={`w-2 h-2 rounded-full transition-all duration-300 ease-in ${
activeIdx === index ? "bg-[#113768]" : "bg-[#b1d3ff]"
}`}
onClick={() => handleDotClick(index)}
style={{ cursor: "pointer" }}
/>
))}
</div>