├── .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 |
{tFooter("text")}
21 |{feature.description}
65 |67 | {description} 68 |
69 |
113 | {endpoint}
114 |
115 | ))}
116 |
124 | {tDoc("endpoints.baseUrl")}{" "}
125 |
134 | https://tn-municipality-api.vercel.app
135 |
136 |
158 | {tDoc("parameters.description")} 159 |
160 |
192 | {param.name}
193 |
194 |
201 | {param.type}
202 |
203 | 212 | {tDoc(`parameters.${param.translationKey}.description`)} 213 |
214 |
231 | {endpoints[param.endpoint]}
232 | {param.example}
233 |
234 |
275 | {`fetch('/api/municipalities')
276 | .then(response => response.json())
277 | .then(data => console.log(data));`}
278 |
279 |
304 | {`fetch('/api/municipalities?name=ariana')
305 | .then(response => response.json())
306 | .then(data => console.log(data));`}
307 |
308 |
333 | {`fetch('/api/municipalities?delegation=ville')
334 | .then(response => response.json())
335 | .then(data => console.log(data));`}
336 |
337 |
362 | {`fetch('/api/municipalities?postalCode=2058')
363 | .then(response => response.json())
364 | .then(data => console.log(data));`}
365 |
366 |
391 | {`fetch('/api/municipalities?name=ariana&delegation=ville')
392 | .then(response => response.json())
393 | .then(data => console.log(data));`}
394 |
395 |
424 | {exampleResponse}
425 |
426 |