Hr Visitors Dashboard
This commit is contained in:
parent
fa5ed66ae2
commit
68482e0a8d
6 changed files with 234 additions and 112 deletions
|
|
@ -6,7 +6,6 @@ import {
|
||||||
Document,
|
Document,
|
||||||
Certificate,
|
Certificate,
|
||||||
ExpenseRequest,
|
ExpenseRequest,
|
||||||
Task,
|
|
||||||
Training,
|
Training,
|
||||||
Reservation,
|
Reservation,
|
||||||
MealMenu,
|
MealMenu,
|
||||||
|
|
@ -15,97 +14,6 @@ import {
|
||||||
SocialPost,
|
SocialPost,
|
||||||
} from '@/types/intranet'
|
} from '@/types/intranet'
|
||||||
|
|
||||||
|
|
||||||
export const mockExpenseRequests: ExpenseRequest[] = [
|
|
||||||
{
|
|
||||||
id: 'exp1',
|
|
||||||
employee: mockEmployees[0],
|
|
||||||
category: 'travel',
|
|
||||||
amount: 850,
|
|
||||||
currency: 'TRY',
|
|
||||||
date: new Date('2024-10-15'),
|
|
||||||
description: 'Ankara ofis ziyareti - uçak bileti',
|
|
||||||
project: 'Intranet v2',
|
|
||||||
receipts: [{ name: 'ucak_bileti.pdf', url: '#', size: '234 KB' }],
|
|
||||||
status: 'approved',
|
|
||||||
approver: mockEmployees[4],
|
|
||||||
approvalDate: new Date('2024-10-16T10:00:00'),
|
|
||||||
creationTime: new Date('2024-10-15T18:00:00'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'exp2',
|
|
||||||
employee: mockEmployees[2],
|
|
||||||
category: 'meal',
|
|
||||||
amount: 320,
|
|
||||||
currency: 'TRY',
|
|
||||||
date: new Date('2024-10-17'),
|
|
||||||
description: 'Müşteri toplantısı - öğle yemeği',
|
|
||||||
receipts: [{ name: 'restoran_fisi.jpg', url: '#', size: '156 KB' }],
|
|
||||||
status: 'pending',
|
|
||||||
creationTime: new Date('2024-10-17T20:00:00'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'exp3',
|
|
||||||
employee: mockEmployees[1],
|
|
||||||
category: 'accommodation',
|
|
||||||
amount: 1200,
|
|
||||||
currency: 'TRY',
|
|
||||||
date: new Date('2024-10-14'),
|
|
||||||
description: 'İzmir workshop - otel konaklaması (2 gece)',
|
|
||||||
project: 'UX Workshop',
|
|
||||||
receipts: [{ name: 'otel_fatura.pdf', url: '#', size: '445 KB' }],
|
|
||||||
status: 'approved',
|
|
||||||
approver: mockEmployees[4],
|
|
||||||
approvalDate: new Date('2024-10-15T09:00:00'),
|
|
||||||
creationTime: new Date('2024-10-14T22:00:00'),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export const mockTasks: Task[] = [
|
|
||||||
{
|
|
||||||
id: 'task1',
|
|
||||||
title: 'API Endpoint Geliştirme',
|
|
||||||
description: "Kullanıcı yönetimi için RESTful API endpoint'leri oluşturulacak",
|
|
||||||
project: 'Intranet v2',
|
|
||||||
assignedTo: [mockEmployees[0]],
|
|
||||||
assignedBy: mockEmployees[4],
|
|
||||||
priority: 'high',
|
|
||||||
status: 'in-progress',
|
|
||||||
dueDate: new Date('2024-10-25'),
|
|
||||||
creationTime: new Date('2024-10-14'),
|
|
||||||
labels: ['backend', 'api'],
|
|
||||||
comments: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'task2',
|
|
||||||
title: 'Dashboard UI Tasarımı',
|
|
||||||
description: 'Yeni dashboard için UI/UX tasarımı yapılacak',
|
|
||||||
project: 'Intranet v2',
|
|
||||||
assignedTo: [mockEmployees[1]],
|
|
||||||
assignedBy: mockEmployees[4],
|
|
||||||
priority: 'medium',
|
|
||||||
status: 'review',
|
|
||||||
dueDate: new Date('2024-10-22'),
|
|
||||||
creationTime: new Date('2024-10-10'),
|
|
||||||
labels: ['design', 'ui/ux'],
|
|
||||||
comments: 5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'task3',
|
|
||||||
title: 'Kubernetes Deployment',
|
|
||||||
description: 'Production ortamı için Kubernetes yapılandırması',
|
|
||||||
project: 'Infrastructure',
|
|
||||||
assignedTo: [mockEmployees[2]],
|
|
||||||
assignedBy: mockEmployees[4],
|
|
||||||
priority: 'urgent',
|
|
||||||
status: 'todo',
|
|
||||||
dueDate: new Date('2024-10-20'),
|
|
||||||
creationTime: new Date('2024-10-17'),
|
|
||||||
labels: ['devops', 'infrastructure'],
|
|
||||||
comments: 1,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
2
|
|
||||||
export const mockDocuments: Document[] = [
|
export const mockDocuments: Document[] = [
|
||||||
{
|
{
|
||||||
id: 'doc1',
|
id: 'doc1',
|
||||||
|
|
@ -980,3 +888,48 @@ export const mockVisitors: Visitor[] = [
|
||||||
photo: 'https://i.pravatar.cc/150?img=68',
|
photo: 'https://i.pravatar.cc/150?img=68',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export const mockExpenseRequests: ExpenseRequest[] = [
|
||||||
|
{
|
||||||
|
id: 'exp1',
|
||||||
|
employee: mockEmployees[0],
|
||||||
|
category: 'travel',
|
||||||
|
amount: 850,
|
||||||
|
currency: 'TRY',
|
||||||
|
date: new Date('2024-10-15'),
|
||||||
|
description: 'Ankara ofis ziyareti - uçak bileti',
|
||||||
|
project: 'Intranet v2',
|
||||||
|
receipts: [{ name: 'ucak_bileti.pdf', url: '#', size: '234 KB' }],
|
||||||
|
status: 'approved',
|
||||||
|
approver: mockEmployees[4],
|
||||||
|
approvalDate: new Date('2024-10-16T10:00:00'),
|
||||||
|
creationTime: new Date('2024-10-15T18:00:00'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'exp2',
|
||||||
|
employee: mockEmployees[2],
|
||||||
|
category: 'meal',
|
||||||
|
amount: 320,
|
||||||
|
currency: 'TRY',
|
||||||
|
date: new Date('2024-10-17'),
|
||||||
|
description: 'Müşteri toplantısı - öğle yemeği',
|
||||||
|
receipts: [{ name: 'restoran_fisi.jpg', url: '#', size: '156 KB' }],
|
||||||
|
status: 'pending',
|
||||||
|
creationTime: new Date('2024-10-17T20:00:00'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'exp3',
|
||||||
|
employee: mockEmployees[1],
|
||||||
|
category: 'accommodation',
|
||||||
|
amount: 1200,
|
||||||
|
currency: 'TRY',
|
||||||
|
date: new Date('2024-10-14'),
|
||||||
|
description: 'İzmir workshop - otel konaklaması (2 gece)',
|
||||||
|
project: 'UX Workshop',
|
||||||
|
receipts: [{ name: 'otel_fatura.pdf', url: '#', size: '445 KB' }],
|
||||||
|
status: 'approved',
|
||||||
|
approver: mockEmployees[4],
|
||||||
|
approvalDate: new Date('2024-10-15T09:00:00'),
|
||||||
|
creationTime: new Date('2024-10-14T22:00:00'),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
@ -82,4 +82,56 @@ export const mockProjectTasks: PsProjectTask[] = [
|
||||||
creationTime: new Date("2024-01-15"),
|
creationTime: new Date("2024-01-15"),
|
||||||
lastModificationTime: new Date("2024-02-08"),
|
lastModificationTime: new Date("2024-02-08"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
projectId: "1",
|
||||||
|
phaseId: "1",
|
||||||
|
phase: mockProjectPhases.find((phase) => phase.id === "1"),
|
||||||
|
taskCode: "TSK-004",
|
||||||
|
name: "Güvenlik Açığı Düzeltme",
|
||||||
|
description: "Kritik güvenlik açığının acil olarak düzeltilmesi gerekiyor",
|
||||||
|
taskType: TaskTypeEnum.Development,
|
||||||
|
status: TaskStatusEnum.InProgress,
|
||||||
|
priority: PriorityEnum.Urgent,
|
||||||
|
assignedTo: "1",
|
||||||
|
assignee: mockEmployees.find((emp) => emp.id === "1"),
|
||||||
|
startDate: new Date("2024-10-20"),
|
||||||
|
endDate: new Date("2024-10-25"),
|
||||||
|
actualStartDate: new Date("2024-10-20"),
|
||||||
|
actualEndDate: undefined,
|
||||||
|
estimatedHours: 20,
|
||||||
|
actualHours: 8,
|
||||||
|
progress: 40,
|
||||||
|
activities: [],
|
||||||
|
comments: [],
|
||||||
|
isActive: true,
|
||||||
|
creationTime: new Date("2024-10-20"),
|
||||||
|
lastModificationTime: new Date("2024-10-20"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5",
|
||||||
|
projectId: "2",
|
||||||
|
phaseId: "2",
|
||||||
|
phase: mockProjectPhases.find((phase) => phase.id === "2"),
|
||||||
|
taskCode: "TSK-005",
|
||||||
|
name: "Performans Optimizasyonu",
|
||||||
|
description: "Uygulama performansının iyileştirilmesi",
|
||||||
|
taskType: TaskTypeEnum.Development,
|
||||||
|
status: TaskStatusEnum.NotStarted,
|
||||||
|
priority: PriorityEnum.High,
|
||||||
|
assignedTo: "2",
|
||||||
|
assignee: mockEmployees.find((emp) => emp.id === "2"),
|
||||||
|
startDate: new Date("2024-10-28"),
|
||||||
|
endDate: new Date("2024-11-15"),
|
||||||
|
actualStartDate: undefined,
|
||||||
|
actualEndDate: undefined,
|
||||||
|
estimatedHours: 100,
|
||||||
|
actualHours: 0,
|
||||||
|
progress: 0,
|
||||||
|
activities: [],
|
||||||
|
comments: [],
|
||||||
|
isActive: true,
|
||||||
|
creationTime: new Date("2024-10-15"),
|
||||||
|
lastModificationTime: new Date("2024-10-15"),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import ExpenseManagement from './widgets/ExpenseManagement'
|
||||||
import UpcomingTrainings from './widgets/UpcomingTrainings'
|
import UpcomingTrainings from './widgets/UpcomingTrainings'
|
||||||
import ActiveReservations from './widgets/ActiveReservations'
|
import ActiveReservations from './widgets/ActiveReservations'
|
||||||
import ActiveSurveys from './widgets/ActiveSurveys'
|
import ActiveSurveys from './widgets/ActiveSurveys'
|
||||||
|
import Visitors from './widgets/Visitors'
|
||||||
|
|
||||||
// Modals
|
// Modals
|
||||||
import SurveyModal from './modals/SurveyModal'
|
import SurveyModal from './modals/SurveyModal'
|
||||||
|
|
@ -92,6 +93,7 @@ const IntranetDashboard: React.FC = () => {
|
||||||
<UpcomingTrainings />
|
<UpcomingTrainings />
|
||||||
<ActiveReservations onNewReservation={() => setShowReservationModal(true)} />
|
<ActiveReservations onNewReservation={() => setShowReservationModal(true)} />
|
||||||
<ActiveSurveys onTakeSurvey={handleTakeSurvey} />
|
<ActiveSurveys onTakeSurvey={handleTakeSurvey} />
|
||||||
|
<Visitors />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="lg:col-span-5 space-y-6">
|
<div className="lg:col-span-5 space-y-6">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { motion } from 'framer-motion'
|
import { motion } from 'framer-motion'
|
||||||
import { FaTimes } from 'react-icons/fa'
|
import { FaTimes } from 'react-icons/fa'
|
||||||
import { Survey } from '../../../mocks/mockIntranet'
|
import { Survey } from '@/types/intranet'
|
||||||
|
|
||||||
interface SurveyModalProps {
|
interface SurveyModalProps {
|
||||||
survey: Survey
|
survey: Survey
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,21 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { FaChartBar, FaClock, FaUsers } from 'react-icons/fa'
|
import { FaChartBar, FaClock, FaUser } from 'react-icons/fa'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { mockTasks } from '../../../mocks/mockIntranet'
|
import { mockProjectTasks } from '../../../mocks/mockProjectTasks'
|
||||||
|
import { PriorityEnum } from '../../../types/common'
|
||||||
|
import { TaskStatusEnum } from '../../../types/ps'
|
||||||
|
|
||||||
const PriorityTasks: React.FC = () => {
|
const PriorityTasks: React.FC = () => {
|
||||||
const priorityTasks = mockTasks
|
const priorityTasks = mockProjectTasks
|
||||||
.filter((t) => t.priority === 'high' || t.priority === 'urgent')
|
.filter((t) => t.priority === PriorityEnum.High || t.priority === PriorityEnum.Urgent)
|
||||||
.slice(0, 3)
|
.slice(0, 3)
|
||||||
|
|
||||||
const getPriorityColor = (priority: string) => {
|
const getPriorityColor = (priority: PriorityEnum) => {
|
||||||
const colors: Record<string, string> = {
|
const colors: Record<PriorityEnum, string> = {
|
||||||
low: 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300',
|
[PriorityEnum.Low]: 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300',
|
||||||
medium: 'bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-300',
|
[PriorityEnum.Normal]: 'bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-300',
|
||||||
high: 'bg-orange-100 dark:bg-orange-900/30 text-orange-600 dark:text-orange-300',
|
[PriorityEnum.High]: 'bg-orange-100 dark:bg-orange-900/30 text-orange-600 dark:text-orange-300',
|
||||||
urgent: 'bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-300',
|
[PriorityEnum.Urgent]: 'bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-300',
|
||||||
}
|
}
|
||||||
return colors[priority]
|
return colors[priority]
|
||||||
}
|
}
|
||||||
|
|
@ -33,21 +35,21 @@ const PriorityTasks: React.FC = () => {
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
className="mt-1 rounded border-gray-300 dark:border-gray-600"
|
className="mt-1 rounded border-gray-300 dark:border-gray-600"
|
||||||
checked={task.status === 'done'}
|
checked={task.status === TaskStatusEnum.Completed}
|
||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
<h3 className="text-sm font-medium text-gray-900 dark:text-white">
|
<h3 className="text-sm font-medium text-gray-900 dark:text-white">
|
||||||
{task.title}
|
{task.name}
|
||||||
</h3>
|
</h3>
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-0.5 text-xs rounded ${getPriorityColor(task.priority)}`}
|
className={`px-2 py-0.5 text-xs rounded ${getPriorityColor(task.priority)}`}
|
||||||
>
|
>
|
||||||
{task.priority === 'urgent' && '🔥 Acil'}
|
{task.priority === PriorityEnum.Urgent && '🔥 Acil'}
|
||||||
{task.priority === 'high' && 'Yüksek'}
|
{task.priority === PriorityEnum.High && 'Yüksek'}
|
||||||
{task.priority === 'medium' && 'Orta'}
|
{task.priority === PriorityEnum.Normal && 'Orta'}
|
||||||
{task.priority === 'low' && 'Düşük'}
|
{task.priority === PriorityEnum.Low && 'Düşük'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-gray-600 dark:text-gray-400 mb-2">
|
<p className="text-xs text-gray-600 dark:text-gray-400 mb-2">
|
||||||
|
|
@ -56,11 +58,11 @@ const PriorityTasks: React.FC = () => {
|
||||||
<div className="flex items-center gap-3 text-xs text-gray-500">
|
<div className="flex items-center gap-3 text-xs text-gray-500">
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<FaClock className="w-3 h-3" />
|
<FaClock className="w-3 h-3" />
|
||||||
{dayjs(task.dueDate).format('DD MMM')}
|
{dayjs(task.endDate).format('DD MMM')}
|
||||||
</span>
|
</span>
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<FaUsers className="w-3 h-3" />
|
<FaUser className="w-3 h-3" />
|
||||||
{task.assignedTo.length} kişi
|
{task.assignee?.firstName || 'Atanmadı'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
113
ui/src/views/intranet/widgets/Visitors.tsx
Normal file
113
ui/src/views/intranet/widgets/Visitors.tsx
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { FaUser, FaUserCheck, FaUserClock } from 'react-icons/fa'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import { mockVisitors } from '../../../mocks/mockIntranet'
|
||||||
|
|
||||||
|
const Visitors: React.FC = () => {
|
||||||
|
const todayVisitors = mockVisitors.filter((visitor) =>
|
||||||
|
dayjs(visitor.visitDate).isSame(dayjs(), 'day')
|
||||||
|
)
|
||||||
|
|
||||||
|
const getStatusIcon = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case 'checked-in':
|
||||||
|
return <FaUserCheck className="w-4 h-4 text-green-600" />
|
||||||
|
case 'checked-out':
|
||||||
|
return <FaUser className="w-4 h-4 text-gray-600" />
|
||||||
|
case 'scheduled':
|
||||||
|
return <FaUserClock className="w-4 h-4 text-blue-600" />
|
||||||
|
default:
|
||||||
|
return <FaUser className="w-4 h-4 text-gray-600" />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusText = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case 'checked-in':
|
||||||
|
return 'Giriş Yaptı'
|
||||||
|
case 'checked-out':
|
||||||
|
return 'Çıkış Yaptı'
|
||||||
|
case 'scheduled':
|
||||||
|
return 'Planlandı'
|
||||||
|
default:
|
||||||
|
return 'Bilinmiyor'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusColor = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case 'checked-in':
|
||||||
|
return 'bg-green-50 dark:bg-green-900/20 border-green-200 dark:border-green-800'
|
||||||
|
case 'checked-out':
|
||||||
|
return 'bg-gray-50 dark:bg-gray-900/20 border-gray-200 dark:border-gray-700'
|
||||||
|
case 'scheduled':
|
||||||
|
return 'bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800'
|
||||||
|
default:
|
||||||
|
return 'bg-gray-50 dark:bg-gray-900/20 border-gray-200 dark:border-gray-700'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
|
||||||
|
<div className="p-6 border-b border-gray-200 dark:border-gray-700">
|
||||||
|
<h2 className="text-lg font-semibold text-gray-900 dark:text-white flex items-center gap-2">
|
||||||
|
<FaUser className="w-5 h-5" />
|
||||||
|
Bugünkü Ziyaretçiler
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div className="p-4 space-y-3">
|
||||||
|
{todayVisitors.length > 0 ? (
|
||||||
|
todayVisitors.map((visitor) => (
|
||||||
|
<div
|
||||||
|
key={visitor.id}
|
||||||
|
className={`p-3 rounded-lg border ${getStatusColor(visitor.status)}`}
|
||||||
|
>
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<img
|
||||||
|
src={visitor.photo}
|
||||||
|
alt={visitor.fullName}
|
||||||
|
className="w-10 h-10 rounded-full border-2 border-gray-300 dark:border-gray-600"
|
||||||
|
/>
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<div className="flex items-center justify-between mb-1">
|
||||||
|
<h4 className="text-sm font-medium text-gray-900 dark:text-white truncate">
|
||||||
|
{visitor.fullName}
|
||||||
|
</h4>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
{getStatusIcon(visitor.status)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-gray-600 dark:text-gray-400 truncate">
|
||||||
|
{visitor.company}
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-gray-500 dark:text-gray-500 mt-1">
|
||||||
|
{visitor.purpose}
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center justify-between mt-2">
|
||||||
|
<span className="text-xs text-gray-500 dark:text-gray-500">
|
||||||
|
{dayjs(visitor.visitDate).format('HH:mm')}
|
||||||
|
</span>
|
||||||
|
<span className="text-xs px-2 py-1 rounded-full bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400">
|
||||||
|
{getStatusText(visitor.status)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{visitor.host && (
|
||||||
|
<p className="text-xs text-gray-500 dark:text-gray-500 mt-1">
|
||||||
|
Karşılayan: {visitor.host.fullName}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<p className="text-sm text-gray-500 dark:text-gray-400 text-center py-4">
|
||||||
|
Bugün ziyaretçi yok
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Visitors
|
||||||
Loading…
Reference in a new issue