diff --git a/src/components/layout/mobile-navigation.tsx b/src/components/layout/mobile-navigation.tsx
new file mode 100644
index 0000000..ea4c308
--- /dev/null
+++ b/src/components/layout/mobile-navigation.tsx
@@ -0,0 +1,46 @@
+import { useEffect } from 'react';
+import { motion, AnimatePresence } from 'framer-motion';
+import { useUI } from '../context/ui.context';
+
+const sidebarVariants = {
+ hidden: { x: '100%' },
+ visible: { x: 0 },
+ exit: { x: '100%' },
+};
+
+const MobileNavigation = () => {
+ const { sidebarDisplay, closeSidebar } = useUI();
+
+ useEffect(() => {
+ if (!sidebarDisplay) {
+ document.body.style.overflow = 'hidden';
+ } else {
+ document.body.style.overflow = 'auto';
+ }
+ }, [sidebarDisplay]);
+console.log("ssssssssssss");
+
+ return (
+
+ {sidebarDisplay && (
+
+
+
+ {/* Add your sidebar content here */}
+
+
+ )}
+
+ );
+};
+
+export default MobileNavigation;
\ No newline at end of file
diff --git a/src/components/mobile-header/hamburger.tsx b/src/components/mobile-header/hamburger.tsx
new file mode 100644
index 0000000..9c6609f
--- /dev/null
+++ b/src/components/mobile-header/hamburger.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import Image from 'next/image';
+import Hamburegure from "../../../public/assets/images/hamburgure.svg";
+import { useUI } from '../context/ui.context';
+import MobileNavigation from '../layout/mobile-navigation';
+
+
+const HamburgerButton: React.FC = () => {
+ const {openSidebar} = useUI()
+ return (
+ <>
+
+ >
+ );
+};
+
+export default HamburgerButton;
\ No newline at end of file
diff --git a/src/components/ui/mobile-search.tsx b/src/components/mobile-header/mobile-search.tsx
similarity index 100%
rename from src/components/ui/mobile-search.tsx
rename to src/components/mobile-header/mobile-search.tsx
diff --git a/src/components/ui/mobile-setting.tsx b/src/components/mobile-header/mobile-setting.tsx
similarity index 100%
rename from src/components/ui/mobile-setting.tsx
rename to src/components/mobile-header/mobile-setting.tsx
diff --git a/src/components/modals/modal-manager.tsx b/src/components/modals/modal-manager.tsx
index 4dd4d54..e087773 100644
--- a/src/components/modals/modal-manager.tsx
+++ b/src/components/modals/modal-manager.tsx
@@ -2,7 +2,7 @@ import { useUI } from "../context/ui.context";
import Modal from "./modal";
import dynamic from "next/dynamic";
// import Newsletter from "../newsletter";
-const SettingModal = dynamic(() => import("@/components/ui/setting"));
+const SettingModal = dynamic(() => import("@/components/modals/setting"));
const SearchModal = dynamic(() => import("@/components/modals/search-modal"));
// const SignUpForm = dynamic(() => import("@components/auth/sign-up-form"));
// const ForgetPasswordForm = dynamic(
diff --git a/src/components/modals/modal.tsx b/src/components/modals/modal.tsx
index 766bfc3..f87bcc9 100644
--- a/src/components/modals/modal.tsx
+++ b/src/components/modals/modal.tsx
@@ -12,7 +12,7 @@ import { fadeInOut } from '@/utils/motion/fade-in-out';
import { zoomOutIn } from '@/utils/motion/zoom-out-in';
import { useUI } from '../context/ui.context';
import useOnClickOutside from '@/utils/use-click-outside';
-import SettingModal from '../ui/setting';
+import SettingModal from './setting';
type ModalProps = {
open?: boolean;
@@ -52,7 +52,6 @@ export default function Modal({
const { closeModal } = useUI();
const modalRootRef = useRef() as DivElementRef;
const modalInnerRef = useRef() as DivElementRef;
- useOnClickOutside(modalInnerRef, () => closeModal());
useEffect(() => {
if (modalInnerRef.current) {
if (open) {
diff --git a/src/components/modals/search-modal.tsx b/src/components/modals/search-modal.tsx
index 0c306c6..dc967fe 100644
--- a/src/components/modals/search-modal.tsx
+++ b/src/components/modals/search-modal.tsx
@@ -1,27 +1,148 @@
import Image from "next/image";
-import React from "react";
-import search from "../../../public/assets/images/Search.svg"
+import React, { useEffect, useState } from "react";
+import search from "../../../public/assets/images/Search.svg";
import { IoMdClose } from "react-icons/io";
+import { useUI } from "../context/ui.context";
+import http from "@/api/http"; // Assuming you have an http utility for API calls
+import Audio from "../../../public/assets/images/Icon ionic-md-musical-notes.svg";
+import NoData from "../../../public/assets/images/NoDataFound.svg";
+import { useRouter } from "next/router";
+import DOMPurify from "dompurify"; // Install with `npm install dompurify`
+
const SearchModal: React.FC = () => {
- console.log("fdasdfasfa");
+ const { closeModal } = useUI();
+ const [value, setValue] = useState("");
+ const [results, setResults] = useState([]);
+ const [counts, setCounts] = useState(null);
+ const [noData, setNoData] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState
(null);
+ const router = useRouter();
+
+ const openDua = (dua: Dua) => {
+ const lastReadDuas = JSON.parse(localStorage.getItem("last-read") || "[]");
+ const updatedDuas = [...lastReadDuas, dua];
+ localStorage.setItem("last-read", JSON.stringify(updatedDuas));
+ const slug = dua.title.toLowerCase().replaceAll(" ", "-");
+ router.push(`/duas/${slug}-${dua.id}`);
+ closeModal();
+ };
+
+ useEffect(() => {
+ setCounts(null);
+ setResults([]);
+ setNoData(false);
+ // If the input is empty, reset results and do not send a request
+ if (value.trim() === "") {
+ setResults([]);
+ setError(null);
+ return;
+ }
+
+ // Set loading state
+ setIsLoading(true);
+ setError(null);
+ // Implement debounce: wait for 500ms after the user stops typing
+ const debounceTimer = setTimeout(() => {
+ // Perform the search API call with the actual user input
+ http
+ .get(`web/mafatih-duas/?search=${encodeURIComponent(value)}`)
+ .then((res) => {
+ setResults(res.data.results);
+ setIsLoading(false);
+ setCounts(res.data.count);
+ if (res.data.count === 0) {
+ setNoData(true);
+ }
+ })
+ .catch((err) => {
+ console.error("Error fetching search results:", err);
+ setError("Failed to fetch search results.");
+ setIsLoading(false);
+ });
+ }, 500); // 500ms debounce duration
+
+ // Cleanup function to cancel the timeout if the value changes before 500ms
+ return () => clearTimeout(debounceTimer);
+ }, [value]);
return (
-
-
-
-
);
};
diff --git a/src/components/ui/range-input.tsx b/src/components/ui/range-input.tsx
index cbdc67b..d5dd447 100644
--- a/src/components/ui/range-input.tsx
+++ b/src/components/ui/range-input.tsx
@@ -1,4 +1,3 @@
-// components/ui/range-input.tsx
import React from 'react';
interface RangeInputProps {
@@ -22,10 +21,11 @@ const RangeInput: React.FC
= ({ value, onChange, disabled = fal
value={value}
onChange={handleChange}
disabled={disabled}
- className={`w-28 h-[2px] ${disabled ? 'bg-gray-400' : 'bg-[#F4846F]'} outline-none transition-opacity duration-150 ease-in-out mr-3`}
+ className={`w-28 h-[2px] outline-none transition-opacity duration-150 ease-in-out mr-3`}
style={{
appearance: 'none',
opacity: disabled ? 0.5 : 1,
+ background: `linear-gradient(to right, #F4846F ${(value - 80) / 1.2}%, #EBEBEB ${(value - 80) / 1.2}%)`,
}}
/>
{value}%
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index 4afe064..c1aaaa9 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -2,10 +2,10 @@ import { FontSettingsProvider } from "@/components/context/font-setting-context"
import { UIProvider } from "@/components/context/ui.context";
import Header from "@/components/layout/header";
import MobileHeader from "@/components/layout/mobile-header";
+import MobileNavigation from "@/components/layout/mobile-navigation";
import SideBar from "@/components/layout/sidebar";
import ManagedModal from "@/components/modals/modal-manager";
import DownloadApp from "@/components/ui/download-app";
-import FooterSticky from "@/components/ui/footer-sticky";
import "@/styles/globals.css";
import type { AppProps } from "next/app";
@@ -24,6 +24,8 @@ export default function App({ Component, pageProps }: AppProps) {
+
+
diff --git a/src/pages/duas/[slug].tsx b/src/pages/duas/[slug].tsx
index cc5f16e..d6178fa 100644
--- a/src/pages/duas/[slug].tsx
+++ b/src/pages/duas/[slug].tsx
@@ -10,7 +10,7 @@ import colorizeVowels from "@/components/utils/colorize-vowels";
import { FaArrowLeft } from "react-icons/fa6";
import { useRouter } from "next/router";
import { DuaComponentProps } from "@/components/utils/types";
-import SettingModal from "@/components/ui/setting";
+import SettingModal from "@/components/modals/setting";
import { useUI } from "@/components/context/ui.context";
import { useFontSettingsContext } from "@/components/context/font-setting-context";
diff --git a/src/utils/motion/fade-in-bottom.ts b/src/utils/motion/fade-in-bottom.ts
new file mode 100644
index 0000000..8388a5b
--- /dev/null
+++ b/src/utils/motion/fade-in-bottom.ts
@@ -0,0 +1,26 @@
+export function fadeInBottom(duration: number = 0.5) {
+ return {
+ hidden: {
+ y: -50, // Start above the viewport
+ transition: {
+ type: "easeInOut",
+ duration: duration,
+ },
+ },
+ visible: {
+ y: 0, // Center position
+ transition: {
+ type: "easeInOut",
+ duration: duration,
+ },
+ },
+ exit: {
+ y: 50, // Exit below the viewport
+ transition: {
+ type: "easeInOut",
+ duration: duration,
+ },
+ },
+ };
+ }
+
\ No newline at end of file