feat: add Settlements, SMS, User detail, and Users management pages
- Implement SettlementsPage for managing settlement requests with approval and rejection functionalities. - Create SmsPage for handling SMS templates, including creation, approval, rejection, and logging. - Add UserDetailPage to display detailed information about users. - Develop UsersPage for listing users with search, view, edit, and delete options. - Introduce new types for User, SmsTemplate, SmsLog, and Settlement to support the new features.
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import React from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { ArrowRightIcon } from '@heroicons/react/24/outline';
|
||||
import { api } from '../lib/api';
|
||||
import type { ApiResponse } from '../lib/api';
|
||||
import type { User } from '../types';
|
||||
import { formatDate, formatDateTime } from '../lib/utils';
|
||||
import PageHeader from '../components/ui/PageHeader';
|
||||
import { ActiveBadge } from '../components/ui/StatusBadge';
|
||||
|
||||
function InfoRow({ label, value }: { label: string; value: React.ReactNode }) {
|
||||
return (
|
||||
<div className="flex items-center justify-between py-3 border-b border-gray-100 last:border-0">
|
||||
<span className="text-sm text-gray-500">{label}</span>
|
||||
<span className="text-sm font-medium text-gray-900">{value ?? '—'}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function UserDetailPage() {
|
||||
const { uuid } = useParams<{ uuid: string }>();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ['user', uuid],
|
||||
queryFn: () => api.get<ApiResponse<User>>(`/api/v1/user-profile/${uuid}`),
|
||||
enabled: !!uuid,
|
||||
});
|
||||
|
||||
const user = data?.data;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageHeader
|
||||
title="جزئیات کاربر"
|
||||
breadcrumbs={[
|
||||
{ label: 'داشبورد', to: '/admin/dashboard' },
|
||||
{ label: 'کاربران', to: '/admin/users' },
|
||||
{ label: 'جزئیات' },
|
||||
]}
|
||||
action={
|
||||
<button
|
||||
onClick={() => navigate('/admin/users')}
|
||||
className="flex items-center gap-2 text-sm text-gray-500 hover:text-gray-800 transition-colors"
|
||||
>
|
||||
<ArrowRightIcon className="w-4 h-4" />
|
||||
بازگشت
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
|
||||
{isLoading ? (
|
||||
<div className="bg-white rounded-2xl border border-gray-100 p-6 space-y-3">
|
||||
{Array.from({ length: 6 }).map((_, i) => (
|
||||
<div key={i} className="h-8 bg-gray-100 rounded-lg animate-pulse" />
|
||||
))}
|
||||
</div>
|
||||
) : user ? (
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6">
|
||||
<h3 className="font-semibold text-gray-800 mb-4">اطلاعات پایه</h3>
|
||||
<InfoRow label="شناسه" value={<span dir="ltr" className="font-mono text-xs">{user.uuid}</span>} />
|
||||
<InfoRow
|
||||
label="نام و نام خانوادگی"
|
||||
value={`${user.first_name ?? ''} ${user.last_name ?? ''}`.trim() || '—'}
|
||||
/>
|
||||
<InfoRow label="موبایل" value={<span dir="ltr">{user.mobile_number}</span>} />
|
||||
<InfoRow label="ایمیل" value={user.email} />
|
||||
<InfoRow
|
||||
label="نقش"
|
||||
value={
|
||||
user.roles.includes('ROLE_ADMIN')
|
||||
? 'ادمین'
|
||||
: user.roles.includes('ROLE_DOCTOR')
|
||||
? 'پزشک'
|
||||
: 'کاربر'
|
||||
}
|
||||
/>
|
||||
<InfoRow label="وضعیت" value={<ActiveBadge active={user.is_active} />} />
|
||||
<InfoRow label="تاریخ ثبتنام" value={formatDate(user.created_at)} />
|
||||
<InfoRow label="آخرین بروزرسانی" value={formatDateTime(user.updated_at)} />
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6">
|
||||
<h3 className="font-semibold text-gray-800 mb-4">نقشها و دسترسیها</h3>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{user.roles.map((role) => (
|
||||
<span key={role} className="px-3 py-1 bg-primary-50 text-primary-700 text-xs rounded-full font-medium">
|
||||
{role}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-white rounded-2xl border border-gray-100 p-16 text-center text-gray-400">
|
||||
کاربری یافت نشد
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user