├── src ├── react-app-env.d.ts ├── pages │ ├── about.tsx │ ├── reciters │ │ ├── index.tsx │ │ └── [reciter].tsx │ ├── [sourateID].tsx │ ├── feedback.tsx │ └── index.tsx ├── assets │ └── quran.png ├── types │ ├── response.ts │ ├── reciter.ts │ ├── translations.ts │ ├── sourate.ts │ └── quran.ts ├── hooks │ ├── index.ts │ ├── useTheme.ts │ ├── useTranslation.ts │ └── useQueryApi.ts ├── translations │ ├── translate.tsx │ ├── index.tsx │ ├── ar.json │ ├── en.json │ └── fr.json ├── store │ ├── index.ts │ ├── theme.ts │ └── translation.ts ├── index.css ├── App.tsx ├── index.tsx ├── components │ ├── DarkModeToggle.tsx │ ├── Reciters │ │ ├── RecitersList.tsx │ │ └── RecitersItem.tsx │ ├── ThemeProvider.tsx │ ├── AppbarLayout │ │ ├── Footer.tsx │ │ ├── index.tsx │ │ ├── Header.tsx │ │ └── Drawer.tsx │ ├── SearchInput.tsx │ ├── Home │ │ ├── SourateLists.tsx │ │ └── SourateItem.tsx │ ├── Sourate │ │ ├── Editions.tsx │ │ └── Aya.tsx │ ├── LoadingSpinner.tsx │ └── Form.tsx ├── libs │ ├── quranApi.ts │ ├── vocalsEditions.json │ └── edition.json ├── routes.tsx └── styles │ └── themeToggle.module.css ├── README.md ├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── postcss.config.js ├── tailwind.config.js ├── .gitignore ├── tsconfig.json └── package.json /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/pages/about.tsx: -------------------------------------------------------------------------------- 1 | export default function About() { 2 | return <>; 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # holy-quran-website 2 | # DEMO : https://holy-quran-website.netlify.app/ 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramzykemmoun/holy-quran-website/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramzykemmoun/holy-quran-website/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramzykemmoun/holy-quran-website/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/assets/quran.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramzykemmoun/holy-quran-website/HEAD/src/assets/quran.png -------------------------------------------------------------------------------- /src/types/response.ts: -------------------------------------------------------------------------------- 1 | export type Response = { 2 | code: number; 3 | status: string; 4 | data: T; 5 | }; 6 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useTranslation } from "./useTranslation"; 2 | export { default as useTheme } from "./useTheme"; 3 | -------------------------------------------------------------------------------- /src/types/reciter.ts: -------------------------------------------------------------------------------- 1 | export interface Reciter { 2 | identifier: string; 3 | language: string; 4 | name: string; 5 | englishName: string; 6 | format: string; 7 | type: string; 8 | } 9 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{js,jsx,ts,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [require("@tailwindcss/line-clamp")], 8 | darkMode: "class", 9 | }; 10 | -------------------------------------------------------------------------------- /src/translations/translate.tsx: -------------------------------------------------------------------------------- 1 | import { FormattedMessage } from "react-intl"; 2 | import { TranslationMessage } from "../types/translations"; 3 | 4 | const translate = (id: TranslationMessage, values: any = {}) => ( 5 | 6 | ); 7 | 8 | export default translate; 9 | -------------------------------------------------------------------------------- /src/store/index.ts: -------------------------------------------------------------------------------- 1 | import theme from "./theme"; 2 | import translation from "./translation"; 3 | import { configureStore } from "@reduxjs/toolkit"; 4 | const store = configureStore({ 5 | reducer: { 6 | theme, 7 | translation, 8 | }, 9 | }); 10 | export type RootState = ReturnType; 11 | export type AppDispatch = typeof store.dispatch; 12 | export default store; 13 | -------------------------------------------------------------------------------- /src/store/theme.ts: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | 3 | const themeSlice = createSlice({ 4 | name: "theme", 5 | initialState: { 6 | isDark: true, 7 | }, 8 | reducers: { 9 | toggleTheme(state) { 10 | state.isDark = !state.isDark; 11 | }, 12 | }, 13 | }); 14 | 15 | export const themeActions = themeSlice.actions; 16 | export default themeSlice.reducer; 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | # Local Netlify folder 26 | .netlify 27 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | body { 6 | margin: 0; 7 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 8 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 9 | sans-serif; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | 14 | @layer components { 15 | .toggle { 16 | @apply transition-colors duration-500; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/hooks/useTheme.ts: -------------------------------------------------------------------------------- 1 | import { AppDispatch, RootState } from "../store/index"; 2 | import { useSelector } from "react-redux"; 3 | import { useDispatch } from "react-redux"; 4 | import { themeActions } from "../store/theme"; 5 | 6 | export default function useTheme() { 7 | const isDark = useSelector((state: RootState) => state.theme.isDark); 8 | const dispatch: AppDispatch = useDispatch(); 9 | const toggleTheme = () => { 10 | dispatch(themeActions.toggleTheme()); 11 | }; 12 | return { isDark, toggleTheme }; 13 | } 14 | -------------------------------------------------------------------------------- /src/store/translation.ts: -------------------------------------------------------------------------------- 1 | import { createSlice, PayloadAction } from "@reduxjs/toolkit"; 2 | import { Locale } from "../types/translations"; 3 | 4 | const translationSlice = createSlice({ 5 | name: "translation", 6 | initialState: navigator.language as Locale, 7 | reducers: { 8 | setTranslation(state, action: PayloadAction) { 9 | return (state = action.payload); 10 | }, 11 | }, 12 | }); 13 | 14 | export const translationActions = translationSlice.actions; 15 | export default translationSlice.reducer; 16 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import AppbarLayout from "./components/AppbarLayout/"; 2 | import Footer from "./components/AppbarLayout/Footer"; 3 | import Router from "./routes"; 4 | import Intl18Provider from "./translations"; 5 | import ThemeProvider from "./components/ThemeProvider"; 6 | 7 | function App() { 8 | return ( 9 | 10 | 11 | 12 | 13 |