feat: add text color
This commit is contained in:
@@ -24,7 +24,7 @@ export default function Dashboard() {
|
||||
</div>
|
||||
|
||||
<div className="border-t pt-6">
|
||||
<h2 className="text-lg font-semibold mb-4">خوش آمدید، {user?.email}</h2>
|
||||
<h2 className="text-lg font-semibold mb-4 text-slate-900">خوش آمدید، {user?.email}</h2>
|
||||
|
||||
{/* Dashboard Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mt-6">
|
||||
|
||||
@@ -40,16 +40,13 @@ export default function LoginPage() {
|
||||
<div className="max-w-md w-full space-y-8">
|
||||
<div>
|
||||
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
|
||||
Admin Login
|
||||
پنل ادمین اپروایجنسی
|
||||
</h2>
|
||||
<p className="mt-2 text-center text-sm text-gray-600">
|
||||
Meditation App Admin Panel
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form className="mt-8 space-y-6" onSubmit={handleSubmit}>
|
||||
<div className="rounded-md shadow-sm -space-y-px">
|
||||
<div>
|
||||
<div className='py-2'>
|
||||
<label htmlFor="auth" className="sr-only">
|
||||
Email
|
||||
</label>
|
||||
@@ -58,8 +55,8 @@ export default function LoginPage() {
|
||||
name="auth"
|
||||
type="text"
|
||||
required
|
||||
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
|
||||
placeholder="Email"
|
||||
className="appearance-none relative block w-full px-3 py-3 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
|
||||
placeholder="ایمیل"
|
||||
value={auth}
|
||||
onChange={(e) => setAuth(e.target.value)}
|
||||
disabled={isLoading}
|
||||
@@ -74,8 +71,8 @@ export default function LoginPage() {
|
||||
name="password"
|
||||
type="password"
|
||||
required
|
||||
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
|
||||
placeholder="Password"
|
||||
className="appearance-none rounded-md relative block w-full px-3 py-3 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
|
||||
placeholder="رمز عبور"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
disabled={isLoading}
|
||||
@@ -99,9 +96,9 @@ export default function LoginPage() {
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isLoading}
|
||||
className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
className="group relative w-full flex justify-center py-3 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{isLoading ? 'Logging in...' : 'Sign in'}
|
||||
{isLoading ? 'کمی صبر کنید' : 'ورود'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -154,7 +154,7 @@ export default function ProductsPage() {
|
||||
id="package"
|
||||
value={selectedPackage?.name || ''}
|
||||
onChange={handlePackageChange}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
>
|
||||
{packages.map((pkg) => (
|
||||
<option key={pkg.id} value={pkg.name || ''}>
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import type { Metadata } from 'next';
|
||||
import './globals.css';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'آرام لند | تمرین تنفسی و مدیتیشن',
|
||||
title: 'پنل ادمین',
|
||||
|
||||
alternates: {
|
||||
canonical: '/',
|
||||
|
||||
@@ -109,7 +109,7 @@ export default function PackageForm({ package: pkg, onSubmit, onCancel, isLoadin
|
||||
required
|
||||
value={formData.name || ''}
|
||||
onChange={handleInputChange}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
placeholder="مثال: com.approagency.meditation"
|
||||
dir="ltr"
|
||||
/>
|
||||
@@ -127,7 +127,7 @@ export default function PackageForm({ package: pkg, onSubmit, onCancel, isLoadin
|
||||
required
|
||||
value={formData.title || ''}
|
||||
onChange={handleInputChange}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
placeholder="مثال: آرام لند"
|
||||
/>
|
||||
</div>
|
||||
@@ -180,7 +180,7 @@ export default function PackageForm({ package: pkg, onSubmit, onCancel, isLoadin
|
||||
name="v1_identifier"
|
||||
value={formData.v1_identifier || ''}
|
||||
onChange={handleInputChange}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -195,7 +195,7 @@ export default function PackageForm({ package: pkg, onSubmit, onCancel, isLoadin
|
||||
name="myket_access_token"
|
||||
value={formData.myket_access_token || ''}
|
||||
onChange={handleInputChange}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -210,7 +210,7 @@ export default function PackageForm({ package: pkg, onSubmit, onCancel, isLoadin
|
||||
name="cafe_config_id"
|
||||
value={formData.cafe_config_id || ''}
|
||||
onChange={handleNumberChange}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -225,7 +225,7 @@ export default function PackageForm({ package: pkg, onSubmit, onCancel, isLoadin
|
||||
name="web_app_url"
|
||||
value={formData.web_app_url || ''}
|
||||
onChange={handleInputChange}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
placeholder="https://example.com"
|
||||
/>
|
||||
</div>
|
||||
@@ -241,7 +241,7 @@ export default function PackageForm({ package: pkg, onSubmit, onCancel, isLoadin
|
||||
name="tries"
|
||||
value={formData.tries || 0}
|
||||
onChange={handleNumberChange}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function PackageList({ packages, onEdit, onDelete, isLoading }: P
|
||||
<div className="bg-white shadow overflow-hidden sm:rounded-lg">
|
||||
<ul className="divide-y divide-gray-200">
|
||||
{packages.map((pkg) => (
|
||||
<li key={pkg.id} className="px-6 py-4 hover:bg-gray-50">
|
||||
<li key={pkg.id} className="px-2 py-4 hover:bg-gray-50">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center space-x-3 space-x-reverse">
|
||||
@@ -44,22 +44,18 @@ export default function PackageList({ packages, onEdit, onDelete, isLoading }: P
|
||||
/>
|
||||
)}
|
||||
<div>
|
||||
<p className="text-sm font-medium text-indigo-600 truncate">
|
||||
<p className="text-sm font-medium text-indigo-600 truncate px-2">
|
||||
{pkg.title || 'بدون عنوان'}
|
||||
</p>
|
||||
<p className="text-sm text-gray-500">
|
||||
<p className="text-sm text-gray-500 px-2">
|
||||
{pkg.name || 'بدون نام'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2 sm:flex sm:justify-between">
|
||||
<div className="sm:flex sm:space-x-4 sm:space-x-reverse">
|
||||
<p className="text-xs text-gray-500">
|
||||
شناسه: {pkg.uuid?.substring(0, 8)}...
|
||||
</p>
|
||||
<p className="text-xs text-gray-500 mt-1 sm:mt-0">
|
||||
تلاشها: {pkg.tries || 0}
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
<p className="text-xs text-gray-500 mt-1 sm:mt-0">
|
||||
آخرین بهروزرسانی: {formatDate(pkg.updated_at)}
|
||||
|
||||
@@ -84,7 +84,7 @@ export default function ProductForm({ product, packageName, onSubmit, onCancel,
|
||||
required
|
||||
value={formData.title || ''}
|
||||
onChange={handleInputChange}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
placeholder="مثال: اشتراک ماهانه"
|
||||
/>
|
||||
</div>
|
||||
@@ -102,7 +102,7 @@ export default function ProductForm({ product, packageName, onSubmit, onCancel,
|
||||
min="0"
|
||||
value={formData.price || ''}
|
||||
onChange={handleInputChange}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
placeholder="مثال: 60000"
|
||||
/>
|
||||
</div>
|
||||
@@ -118,7 +118,7 @@ export default function ProductForm({ product, packageName, onSubmit, onCancel,
|
||||
required
|
||||
value={formData.type || 4}
|
||||
onChange={handleInputChange}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
>
|
||||
{Object.entries(PRODUCT_TYPES).map(([value, label]) => (
|
||||
<option key={value} value={value}>
|
||||
@@ -139,7 +139,7 @@ export default function ProductForm({ product, packageName, onSubmit, onCancel,
|
||||
type="text"
|
||||
value={newDescription}
|
||||
onChange={(e) => setNewDescription(e.target.value)}
|
||||
className="flex-1 px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="flex-1 px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
placeholder="ویژگی جدید را وارد کنید"
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
|
||||
@@ -50,7 +50,7 @@ export default function PackageSelector({ token, selectedPackage, onPackageChang
|
||||
value={selectedPackage || ''}
|
||||
onChange={handleChange}
|
||||
disabled={loading || isLoading}
|
||||
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm disabled:opacity-50"
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm disabled:opacity-50"
|
||||
>
|
||||
{loading ? (
|
||||
<option>در حال بارگذاری...</option>
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function UserSearch({ onSearch, isLoading }: UserSearchProps) {
|
||||
<input
|
||||
type="text"
|
||||
id="search"
|
||||
className="block w-full pr-10 pl-3 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
className="block w-full pr-10 pl-3 py-2 border text-slate-900 border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
placeholder="جستجو با ایمیل یا شماره موبایل..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
|
||||
@@ -98,9 +98,19 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
}
|
||||
}
|
||||
|
||||
// Clear localStorage
|
||||
localStorage.removeItem('auth_token');
|
||||
localStorage.removeItem('auth_user');
|
||||
|
||||
// Clear cookie - multiple methods to ensure it's removed
|
||||
document.cookie = 'auth_token=; path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=Strict';
|
||||
document.cookie = 'auth_token=; path=/admin; expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=Strict';
|
||||
|
||||
// Alternative: Clear all cookies
|
||||
document.cookie.split(";").forEach(function (c) {
|
||||
document.cookie = c.replace(/^ +/, "").replace(/=.*/, "=; path=/; expires=" + new Date().toUTCString() + ";");
|
||||
});
|
||||
|
||||
setState({
|
||||
user: null,
|
||||
token: null,
|
||||
@@ -108,7 +118,9 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
error: null,
|
||||
});
|
||||
|
||||
router.push('/admin/login');
|
||||
// Force hard navigation instead of router.push
|
||||
window.location.href = '/admin/login';
|
||||
// router.push('/admin/login');
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ export const authApi = {
|
||||
},
|
||||
|
||||
logout: async (token: string): Promise<void> => {
|
||||
return apiClient.post('/auth/logout', {}, token);
|
||||
return apiClient.put('/auth/logout', {}, token);
|
||||
},
|
||||
|
||||
getProfile: async (token: string): Promise<any> => {
|
||||
|
||||
@@ -37,7 +37,6 @@ export const packagesApi = {
|
||||
const formData = new FormData();
|
||||
|
||||
// Add method spoofing for Laravel
|
||||
formData.append('_method', 'PUT');
|
||||
|
||||
// Append all fields to FormData
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
|
||||
Reference in New Issue
Block a user