Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,248 changes: 1,044 additions & 204 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"react-audio-player": "^0.17.0",
"react-confetti": "^6.1.0",
"react-dom": "^18.2.0",
"react-icons": "^5.5.0",
"react-infinite-scroll-component": "^6.1.0",
"react-joyride": "^2.9.3",
"react-redux": "^9.1.0",
Expand Down Expand Up @@ -102,9 +103,11 @@
]
},
"devDependencies": {
"@babel/eslint-parser": "^7.28.5",
"@mui/styles": "^5.15.10",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-prettier": "^3.4.0",
"husky": "^9.0.11",
"lint-staged": "^11.0.0",
Expand Down
87 changes: 60 additions & 27 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,71 @@
href="https://fonts.googleapis.com/css2?family=Quicksand&display=swap"
rel="stylesheet"
/>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Devanagari&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Baloo+2&display=swap" rel="stylesheet" />
<link
href="https://fonts.googleapis.com/css2?family=Noto+Sans+Devanagari&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Baloo+2&display=swap"
rel="stylesheet"
/>
<link href="https://fonts.cdnfonts.com/css/bad-comic" rel="stylesheet" />
<script src="./js/jquery-3.7.0.min.js" defer></script>
<title>EkStep</title>

<!-- Content Security Policy -->
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self' https://cdn.jsdelivr.net/npm/[email protected]/dist/confetti.browser.min.js 'unsafe-eval';
style-src 'self' https://fonts.googleapis.com https://fonts.cdnfonts.com 'unsafe-inline';
object-src 'none';
base-uri 'self';
connect-src 'self' *.theall.ai https://all-dev-storage.s3.ap-south-1.amazonaws.com https://all-dev-content-service.s3.ap-south-1.amazonaws.com https://all-prod-content-service.s3.ap-south-1.amazonaws.com blob: https://huggingface.co https://cas-bridge.xethub.hf.co https://cdn.jsdelivr.net;
font-src 'self' https://fonts.googleapis.com https://fonts.cdnfonts.com https://fonts.gstatic.com;
frame-src 'self' https://www.google.com https://www.gstatic.com https://www.youtube.com https://www.youtube-nocookie.com;
img-src 'self' data: blob:
https://images.squarespace-cdn.com
https://all-prod-content-service.s3.ap-south-1.amazonaws.com
https://all-dev-content-service.s3.ap-south-1.amazonaws.com
https://s3.ap-south-1.amazonaws.com
https://raw.githubusercontent.com
https://cdn.jsdelivr.net;
https://github.com
manifest-src 'self';
media-src 'self' blob: https://all-prod-content-service.s3.ap-south-1.amazonaws.com https://all-dev-content-service.s3.ap-south-1.amazonaws.com https://raw.githubusercontent.com https://github.com;
worker-src 'self' blob: https://d114esnbvw5tst.cloudfront.net;
form-action 'self';
frame-ancestors 'self';
" />


<meta
http-equiv="Content-Security-Policy"
content="
default-src 'self';
script-src 'self' 'unsafe-eval'
https://cdn.jsdelivr.net/npm/[email protected]/dist/confetti.browser.min.js;
script-src-elem 'self' 'unsafe-eval';
style-src 'self' 'unsafe-inline'
https://fonts.googleapis.com
https://fonts.cdnfonts.com;
style-src-elem 'self' 'unsafe-inline'
https://fonts.googleapis.com
https://fonts.cdnfonts.com
https://www.gstatic.com;
font-src 'self'
https://fonts.googleapis.com
https://fonts.cdnfonts.com
https://fonts.gstatic.com;
img-src 'self' data: blob:
https://images.squarespace-cdn.com
https://all-prod-content-service.s3.ap-south-1.amazonaws.com
https://all-dev-content-service.s3.ap-south-1.amazonaws.com
https://s3.ap-south-1.amazonaws.com
https://raw.githubusercontent.com
https://cdn.jsdelivr.net
https://github.com
https://placehold.co;
media-src 'self' blob:
https://all-prod-content-service.s3.ap-south-1.amazonaws.com
https://all-dev-content-service.s3.ap-south-1.amazonaws.com
https://raw.githubusercontent.com https://github.com;
connect-src 'self' blob:
http://localhost:3000
ws://localhost:*
ws://127.0.0.1:*
https://www.google.com
*.theall.ai
https://all-dev-storage.s3.ap-south-1.amazonaws.com
https://all-prod-storage.s3.ap-south-1.amazonaws.com
https://all-dev-content-service.s3.ap-south-1.amazonaws.com
https://all-prod-content-service.s3.ap-south-1.amazonaws.com
https://huggingface.co
https://cas-bridge.xethub.hf.co
https://cdn.jsdelivr.net;
form-action 'self';
object-src 'none';
base-uri 'self';
manifest-src 'self';
frame-src 'self';
worker-src 'self' blob: https://d114esnbvw5tst.cloudfront.net;
"
/>
</head>
<body>
<div id="root" />
Expand Down
Binary file added src/assets/Phonics_Vocabulary_images/apple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/ball.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/cat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/dog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/egg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/fish.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/goat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/hat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/igloo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/jam.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/kite.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/lion.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/monkey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/nest.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/orange.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/parrot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/queen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/rabbit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/sun.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/tiger.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/van.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/watch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/yak.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Phonics_Vocabulary_images/zebra.png
95 changes: 95 additions & 0 deletions src/components/Practice/Phonics_Vocabulary/AlphabetStrip.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React, { useRef } from "react";
import { ChevronLeft, ChevronRight } from "@mui/icons-material";
import { IconButton } from "@mui/material";

const AlphabetStrip = ({ data = [], completedLetters = [] }) => {
const scrollRef = useRef(null);

const scroll = (direction) => {
if (scrollRef.current) {
const scrollAmount = 200;
scrollRef.current.scrollBy({
left: direction === "left" ? -scrollAmount : scrollAmount,
behavior: "smooth",
});
}
};

return (
<div style={styles.container}>
<IconButton onClick={() => scroll("left")} aria-label="scroll left">
<ChevronLeft fontSize="large" />
</IconButton>
<div ref={scrollRef} style={styles.scrollContainer}>
{data.map((item) => {
const isCompleted = completedLetters.includes(item.letter);
return (
<div
key={item.letter}
style={{
...styles.letterCircle,
backgroundColor: isCompleted
? "var(--success-color)"
: "#bdc3c7", // Green if completed, Grey if not
color: "white",
transform: isCompleted ? "scale(1.1)" : "scale(1)",
}}
title={item.wordText}
>
{item.letter}
</div>
);
})}
</div>
<IconButton
onClick={() => scroll("right")}
aria-label="scroll right"
fontSize="large"
>
<ChevronRight fontSize="large" />
</IconButton>
</div>
);
};

const styles = {
container: {
width: "100%",
padding: "0.8rem 0",
backgroundColor: "rgba(0,0,0,0.1)",
display: "flex",
justifyContent: "center",
alignItems: "center",
margin: "10px 0",
borderRadius: "15px",
},
scrollContainer: {
display: "flex",
gap: "12px",
overflowX: "auto",
padding: "10px 5px", // Reduced horizontal padding as arrows are external
maxWidth: "90%", // Adjusted to make room for arrows
scrollbarWidth: "none",
msOverflowStyle: "none",
scrollBehavior: "smooth",
},
letterCircle: {
width: "50px",
height: "50px",
borderRadius: "50%",
display: "flex",
alignItems: "center",
justifyContent: "center",
fontSize: "1.2rem",
fontWeight: "bold",
fontFamily: "var(--font-secondary)",
flexShrink: 0,
transition: "all 0.3s ease",
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
cursor: "default",
textAlign: "center",
padding: "2px",
},
};

export default AlphabetStrip;
171 changes: 171 additions & 0 deletions src/components/Practice/Phonics_Vocabulary/Card.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import React from "react";
import { FaVolumeUp, FaRedo, FaPause } from "react-icons/fa";
import { useSpeech } from "./useSpeech";

/**
* Reusable Card component for learning alphabets or words.
* @param {Object} props
* @param {Object} props.item - Data item containing letter, wordText, image etc.
* @param {string} props.language - 'en' or 'ta'
* @param {boolean} props.isCompleted - Completion status
* @param {Function} props.onComplete - Callback when card task is finished
* @param {Function} props.onReset - Callback to undo progress
*/
const Card = ({
item,
language = "en",
mode = "alphabet",
isCompleted,
onComplete,
onReset,
}) => {
const { playSpeech, cancelSpeech, isSpeaking } = useSpeech();

const handlePlay = (e) => {
if (e) e.stopPropagation();

if (isSpeaking) {
cancelSpeech();
} else {
playSpeech(mode === "word" ? item.wordText : item.letter, language);
if (onComplete) onComplete(item.letter);
}
};

const handleReset = (e) => {
if (e) e.stopPropagation();
if (onReset) onReset(item.letter);
};

const displayText = mode === "word" ? item.wordText : item.letter;
const isWord = mode === "word";

return (
<div
style={{
...styles.card,
borderColor: item.color || "var(--primary-color)",
boxShadow: isCompleted
? "0 8px 15px rgba(46, 204, 113, 0.2)"
: "0 4px 6px rgba(0,0,0,0.1)",
transform: isCompleted ? "scale(1.02)" : "scale(1)",
opacity: isCompleted ? 1 : 0.9,
}}
onClick={handlePlay}
>
<div style={styles.content}>
{item.image ? (
<div style={styles.columnContainer}>
<img src={item.image} alt={item.wordText} style={styles.image} />
<span
style={{
...styles.text,
color: item.color,
fontSize: isWord ? "1.5rem" : "2.8rem",
}}
>
{displayText}
</span>
</div>
) : (
<span
style={{
...styles.text,
color: item.color,
fontSize: isWord ? "2rem" : "2.8rem",
}}
>
{displayText}
</span>
)}
</div>

<div style={styles.controls}>
<button
onClick={handlePlay}
style={{
...styles.iconButton,
backgroundColor: item.color || "var(--primary-color)",
}}
title={isSpeaking ? "Pause" : "Play Sound"}
>
{isSpeaking ? <FaPause /> : <FaVolumeUp />}
</button>
<button
onClick={handleReset}
style={{ ...styles.iconButton, backgroundColor: "#95a5a6" }}
title="Reset Progress"
>
<FaRedo />
</button>
</div>
</div>
);
};

const styles = {
card: {
backgroundColor: "var(--card-bg)",
borderRadius: "20px",
borderWidth: "4px",
borderStyle: "solid",
height: "var(--card-height)",
width: "100%",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "space-between",
padding: "0.6rem",
position: "relative",
transition: "all 0.2s ease",
cursor: "pointer",
},
content: {
flex: 1,
display: "flex",
alignItems: "center",
justifyContent: "center",
width: "100%",
},
text: {
fontSize: "2.8rem",
fontFamily: "var(--font-secondary)",
fontWeight: "bold",
},
columnContainer: {
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "4px",
},
image: {
width: "70px",
height: "70px",
objectFit: "contain",
borderRadius: "10px",
marginBottom: "1px",
},
controls: {
display: "flex",
gap: "8px",
marginTop: "auto",
width: "100%",
justifyContent: "center",
},
iconButton: {
width: "32px",
height: "32px",
borderRadius: "50%",
color: "white",
fontSize: "0.9rem",
border: "none",
display: "flex",
alignItems: "center",
justifyContent: "center",
cursor: "pointer",
boxShadow: "0 2px 4px rgba(0,0,0,0.2)",
transition: "transform 0.1s",
},
};

export default Card;
Loading