├── .husky └── pre-commit ├── app ├── favicon.ico ├── api │ └── municipalities │ │ ├── near │ │ └── route.ts │ │ └── route.ts ├── [locale] │ ├── layout.tsx │ └── page.tsx └── globals.css ├── postcss.config.mjs ├── public ├── vercel.svg ├── window.svg ├── file.svg ├── logo.svg ├── globe.svg └── next.svg ├── .eslintrc.json ├── middleware.ts ├── next.config.ts ├── components.json ├── i18n ├── config.ts └── locales │ ├── ar.json │ └── en.json ├── components ├── Footer.tsx ├── ui │ ├── label.tsx │ ├── textarea.tsx │ ├── input.tsx │ ├── select.tsx │ ├── button.tsx │ └── card.tsx ├── StickyGitHubButton.tsx ├── FeaturesSection.tsx ├── ScrollToTop.tsx ├── HeroSection.tsx ├── StatsSection.tsx ├── ApiPlayground.tsx ├── DocumentationSection.tsx └── Navbar.tsx ├── .gitignore ├── tsconfig.json ├── lib └── utils.ts ├── package.json ├── SEARCH_ENHANCEMENT.md └── README.md /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npx lint-staged -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/youssef-of-web/tn-municipality-api/HEAD/app/favicon.ico -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: ["@tailwindcss/postcss"], 3 | }; 4 | 5 | export default config; 6 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next/core-web-vitals", "next/typescript"], 3 | "rules": { 4 | "@typescript-eslint/no-explicit-any": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /middleware.ts: -------------------------------------------------------------------------------- 1 | import createMiddleware from "next-intl/middleware"; 2 | 3 | export default createMiddleware({ 4 | locales: ["en", "ar"], 5 | defaultLocale: "en", 6 | }); 7 | 8 | export const config = { 9 | matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"], 10 | }; 11 | -------------------------------------------------------------------------------- /next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | import createNextIntlPlugin from "next-intl/plugin"; 3 | const withNextIntl = createNextIntlPlugin("./i18n/config.ts"); 4 | const nextConfig: NextConfig = { 5 | /* config options here */ 6 | }; 7 | 8 | export default withNextIntl(nextConfig); 9 | -------------------------------------------------------------------------------- /public/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "app/globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } 22 | -------------------------------------------------------------------------------- /i18n/config.ts: -------------------------------------------------------------------------------- 1 | import { getRequestConfig } from "next-intl/server"; 2 | 3 | const locales = ["en", "ar"] as const; 4 | 5 | export default getRequestConfig(async ({ locale }) => { 6 | // Validate that the incoming locale is valid 7 | if (!locales.includes(locale as (typeof locales)[number])) { 8 | // Return default locale instead of throwing notFound 9 | locale = "en"; 10 | } 11 | 12 | return { 13 | locale: locale as string, 14 | messages: (await import(`./locales/${locale}.json`)).default, 15 | }; 16 | }); 17 | -------------------------------------------------------------------------------- /components/Footer.tsx: -------------------------------------------------------------------------------- 1 | import { useTranslations } from "next-intl"; 2 | 3 | interface FooterProps { 4 | className?: string; 5 | } 6 | 7 | export function Footer({ className }: FooterProps) { 8 | const tFooter = useTranslations("footer"); 9 | return ( 10 |
20 |

{tFooter("text")}

21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /.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.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env* 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | M 18 | 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import * as LabelPrimitive from "@radix-ui/react-label"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | function Label({ 9 | className, 10 | ...props 11 | }: React.ComponentProps) { 12 | return ( 13 | 21 | ); 22 | } 23 | 24 | export { Label }; 25 | -------------------------------------------------------------------------------- /lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | 8 | // Utility function to calculate distance between two geographical points 9 | export function haversineDistance( 10 | lat1: number, 11 | lon1: number, 12 | lat2: number, 13 | lon2: number, 14 | ): number { 15 | const R = 6371; 16 | const toRad = (deg: number): number => deg * (Math.PI / 180); 17 | const dLat = toRad(lat2 - lat1); 18 | const dLon = toRad(lon2 - lon1); 19 | 20 | const a = 21 | Math.sin(dLat / 2) ** 2 + 22 | Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2; 23 | 24 | const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 25 | return R * c; 26 | } 27 | -------------------------------------------------------------------------------- /components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { 6 | return ( 7 |