diff --git a/messages/ar.json b/messages/ar.json
new file mode 100644
index 0000000..2e55808
--- /dev/null
+++ b/messages/ar.json
@@ -0,0 +1,5 @@
+{
+ "Home": {
+ "title": "مرحبا"
+ }
+}
diff --git a/messages/en.json b/messages/en.json
new file mode 100644
index 0000000..6e88cea
--- /dev/null
+++ b/messages/en.json
@@ -0,0 +1,5 @@
+{
+ "Home": {
+ "title": "hello"
+ }
+}
diff --git a/messages/fa.json b/messages/fa.json
index 24e9065..9cf9fe4 100644
--- a/messages/fa.json
+++ b/messages/fa.json
@@ -1,4 +1,5 @@
-{
- "loading": "درحال دریافت داده",
- "error_fetch_data": "مشکلی در دریافت داده رخ داده است."
-}
+{
+ "Home": {
+ "title": "سلام"
+ }
+}
diff --git a/messages/ku.json b/messages/ku.json
new file mode 100644
index 0000000..2e55808
--- /dev/null
+++ b/messages/ku.json
@@ -0,0 +1,5 @@
+{
+ "Home": {
+ "title": "مرحبا"
+ }
+}
diff --git a/next-env.d.ts b/next-env.d.ts
index 9edff1c..c4b7818 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,6 +1,6 @@
///
///
-import "./.next/types/routes.d.ts";
+import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/package.json b/package.json
index 9b32e57..f907ae5 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "name": "witelflix",
+ "name": "cinematales",
"private": true,
"scripts": {
"dev": "next dev",
diff --git a/src/app/layout.tsx b/src/app/[locale]/layout.tsx
similarity index 50%
rename from src/app/layout.tsx
rename to src/app/[locale]/layout.tsx
index e06c8d3..7303fe5 100644
--- a/src/app/layout.tsx
+++ b/src/app/[locale]/layout.tsx
@@ -1,59 +1,55 @@
-import { ClientAppProvider } from "@/providers/ClientAppProvider";
-import "@/styles/globals.css";
-import type { Metadata } from "next";
-import { getLocale, getMessages } from "next-intl/server";
-import { NextIntlClientProvider } from "next-intl";
-
-export const metadata: Metadata = {
- title: {
- template: "%s | Theater of dreams",
- default: "Theater of dreams",
- },
- description: "Theater of dreams",
- authors: {
- name: "شرکت دانش بنیان ویرا ارتباطات یکتا تلفن (وایتل)",
- url: "https://witel.ir",
- },
-
- manifest: "/manifest.json",
- icons: {
- icon: "/logo/192px.png",
- apple: "/logo/512px.png",
- },
-};
-export const viewport = {
- width: "device-width",
- initialScale: 1,
- maximumScale: 1,
-};
-
-export default async function RootLayout({ children }: { children: React.ReactNode }) {
- const locale = await getLocale();
- const messages = await getMessages({ locale });
- return (
-
-
- {/* Prevent theme flicker before hydration */}
-
-
-
-
-
- {children}
-
-
-
- );
-}
+import { getDirection } from "@/i18n/direction";
+import { routing } from "@/i18n/routing";
+import { ClientAppProvider } from "@/providers/ClientAppProvider";
+import "@/styles/globals.css";
+import type { Metadata } from "next";
+import { hasLocale, NextIntlClientProvider } from "next-intl";
+import { getMessages } from "next-intl/server";
+import { notFound } from "next/navigation";
+
+export const metadata: Metadata = {
+ title: "Theater of dreams",
+};
+
+export default async function RootLayout({
+ children,
+ params,
+}: Readonly<{
+ children: React.ReactNode;
+ params: Promise<{ locale: string }>;
+}>) {
+ const { locale } = await params;
+ if (!hasLocale(routing.locales, locale)) {
+ notFound();
+ }
+
+ const messages = await getMessages();
+ const dir = getDirection(locale);
+
+ return (
+
+
+ {/* Prevent theme flicker before hydration */}
+
+
+
+
+
+ {children}
+
+
+
+ );
+}
diff --git a/src/app/[locale]/page.tsx b/src/app/[locale]/page.tsx
new file mode 100644
index 0000000..b634e00
--- /dev/null
+++ b/src/app/[locale]/page.tsx
@@ -0,0 +1,14 @@
+import ComponentsConteiner from "@/components/ComponentsConteiner";
+import { useTranslations } from "next-intl";
+
+export default function Home() {
+ const t = useTranslations("Home");
+ return (
+
+ {t("title")}
+ This project was generated completely offline.
+
+
+ );
+}
+
diff --git a/src/app/page.tsx b/src/app/page.tsx
deleted file mode 100644
index 405f873..0000000
--- a/src/app/page.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import ThemeToggle from "@/components/UI/ThemeToggle";
-
-export default function Home() {
- return (
-
-
- Offline Next.js Template 🚀
- This project was generated completely offline.
-
- );
-}
diff --git a/src/components/ComponentsConteiner.tsx b/src/components/ComponentsConteiner.tsx
new file mode 100644
index 0000000..d7f5443
--- /dev/null
+++ b/src/components/ComponentsConteiner.tsx
@@ -0,0 +1,27 @@
+"use client";
+
+import { useState } from "react";
+import PrimaryButton from "./buttons/PrimaryButton";
+import ThemeToggle from "./UI/ThemeToggle";
+import { Home } from "lucide-react";
+
+export default function ComponentsConteiner() {
+ const [isLoading, setIsloading] = useState(false);
+ function dummyLoading() {
+ setIsloading(true);
+ setTimeout(() => {
+ setIsloading(false);
+ }, 1500);
+ }
+ return (
+
+
+
+
dummyLoading()} loading={isLoading}>
+
+ test icon
+
+
+
+ );
+}
diff --git a/src/components/buttons/PrimaryButton.tsx b/src/components/buttons/PrimaryButton.tsx
new file mode 100644
index 0000000..9dacf3c
--- /dev/null
+++ b/src/components/buttons/PrimaryButton.tsx
@@ -0,0 +1,69 @@
+"use client";
+
+import { cn } from "@/lib/utils";
+import { AnimatePresence, motion } from "framer-motion";
+import { LoaderPinwheel } from "lucide-react";
+
+type PrimaryButtonProps = React.ButtonHTMLAttributes & {
+ loading?: boolean;
+ children: React.ReactNode;
+};
+
+export default function PrimaryButton({ children, loading, className, onClick }: PrimaryButtonProps) {
+ return (
+
+ );
+}
diff --git a/src/i18n/direction.ts b/src/i18n/direction.ts
new file mode 100644
index 0000000..13102be
--- /dev/null
+++ b/src/i18n/direction.ts
@@ -0,0 +1,12 @@
+export type Direction = "ltr" | "rtl";
+
+export const localeDirectionMap: Record = {
+ en: "ltr",
+ ar: "rtl",
+ ku: "rtl",
+ fa: "rtl",
+};
+
+export function getDirection(locale: string): Direction {
+ return localeDirectionMap[locale] ?? "ltr";
+}
diff --git a/src/i18n/navigation.ts b/src/i18n/navigation.ts
new file mode 100644
index 0000000..5024e59
--- /dev/null
+++ b/src/i18n/navigation.ts
@@ -0,0 +1,4 @@
+import { createNavigation } from 'next-intl/navigation'
+import { routing } from './routing'
+
+export const { Link, redirect, usePathname, useRouter, getPathname } = createNavigation(routing)
diff --git a/src/i18n/request.ts b/src/i18n/request.ts
index fd552f5..76cadd2 100644
--- a/src/i18n/request.ts
+++ b/src/i18n/request.ts
@@ -1,12 +1,13 @@
-import { cookies } from "next/headers";
-import { getRequestConfig } from "next-intl/server";
-
-export default getRequestConfig(async () => {
- const cookieStore = await cookies();
- const locale = cookieStore.get("language")?.value || "fa";
-
- return {
- locale,
- messages: (await import(`../../messages/${locale}.json`)).default,
- };
-});
+import { getRequestConfig } from "next-intl/server";
+import { hasLocale } from "next-intl";
+import { routing } from "./routing";
+
+export default getRequestConfig(async ({ requestLocale }) => {
+ const requested = await requestLocale;
+ const locale = hasLocale(routing.locales, requested) ? requested : routing.defaultLocale;
+
+ return {
+ locale,
+ messages: (await import(`../../messages/${locale}.json`)).default,
+ };
+});
diff --git a/src/i18n/routing.ts b/src/i18n/routing.ts
new file mode 100644
index 0000000..066f761
--- /dev/null
+++ b/src/i18n/routing.ts
@@ -0,0 +1,7 @@
+import { defineRouting } from "next-intl/routing";
+
+export const routing = defineRouting({
+ locales: ["en", "ar", "ku", "fa"],
+ defaultLocale: "en",
+ localePrefix: "never",
+});
diff --git a/src/i18n/useDirection.ts b/src/i18n/useDirection.ts
new file mode 100644
index 0000000..875fe61
--- /dev/null
+++ b/src/i18n/useDirection.ts
@@ -0,0 +1,9 @@
+'use client'
+
+import { useLocale } from 'next-intl'
+import { Direction, getDirection } from './direction'
+
+export function useDirection(): Direction {
+ const locale = useLocale()
+ return getDirection(locale)
+}
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
new file mode 100644
index 0000000..fed2fe9
--- /dev/null
+++ b/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from 'clsx'
+import { twMerge } from 'tailwind-merge'
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs))
+}
diff --git a/src/proxy.ts b/src/proxy.ts
new file mode 100644
index 0000000..124b978
--- /dev/null
+++ b/src/proxy.ts
@@ -0,0 +1,8 @@
+import createMiddleware from 'next-intl/middleware'
+import { routing } from './i18n/routing'
+
+export default createMiddleware(routing)
+
+export const config = {
+ matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)',
+}
diff --git a/src/styles/globals.css b/src/styles/globals.css
index 330552b..657222b 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -24,20 +24,58 @@ body {
margin: 0;
}
-@theme {
- --color-primary: #cbd5e1;
- --color-text: #273343;
+button {
+ cursor: pointer;
+}
- /* constants */
- --color-neo-aqua: #16a795;
- --color-core-red: #ef4444;
- --color-warning: #eedd55;
- --color-information: #0ea5e9;
- --color-error: #ef4444;
- --color-success: #22c55e;
+@theme {
+ /* Core */
+ --color-background: #f4f6f8;
+ --color-text: #1e242e;
+
+ /* Brand */
+ --color-primary: #2a7fff;
+ --color-secondary: #64748b;
+ --color-accent: #ff6b3d;
+
+ /* Feedback */
+ --color-warning: #f5c04f;
+ --color-information: #3abff8;
+ --color-error: #ef5350;
+ --color-success: #4ade80;
+
+ /* Surfaces */
+ --color-surface: #ffffff;
+ --color-surface-alt: #e9eef2;
+ --color-border: #d4d9df;
+ --color-muted-text: #6c7480;
+
+ /* Overlays */
+ --color-overlay-light: rgba(0, 0, 0, 0.05);
+ --color-overlay-medium: rgba(0, 0, 0, 0.15);
+ --color-overlay-strong: rgba(0, 0, 0, 0.35);
+
+ /* Gradients */
+ --gradient-primary: linear-gradient(135deg, #2a7fff, #1a5fd1);
+ --gradient-accent: linear-gradient(135deg, #ff6b3d, #ff784d);
}
[data-theme="dark"] {
- --color-primary: #273343;
- --color-text: #cbd5e1;
+ --color-background: #1a1f27;
+ --color-text: #e5e9f0;
+
+ --color-secondary: #94a3b8;
+ --color-accent: #ff8a5c;
+
+ --color-surface: #232833;
+ --color-surface-alt: #2c323e;
+ --color-border: #3a404c;
+ --color-muted-text: #a6aebc;
+
+ --color-overlay-light: rgba(255, 255, 255, 0.05);
+ --color-overlay-medium: rgba(255, 255, 255, 0.12);
+ --color-overlay-strong: rgba(255, 255, 255, 0.25);
+
+ --gradient-primary: linear-gradient(135deg, #63a6ff, #3d7dce);
+ --gradient-accent: linear-gradient(135deg, #ff8a5c, #ff9c75);
}