Intranet dil keylerin düzenlemesi

This commit is contained in:
Sedat ÖZTÜRK 2026-01-27 11:25:39 +03:00
parent b0eafa5018
commit 265d203b95
28 changed files with 1441 additions and 201 deletions

File diff suppressed because it is too large Load diff

View file

@ -121,7 +121,7 @@ function RolesPermission({
setTimeout(async () => {
getConfig(true)
}, 6000)
}, 3000)
}
function getPermissionsWithGroupName(groups: PermissionGroupDto[]): PermissionWithGroupName[] {

View file

@ -104,7 +104,7 @@ function UsersPermission({
setTimeout(async () => {
getConfig(true)
}, 6000)
}, 3000)
}
function getPermissionsWithGroupName(groups: PermissionGroupDto[]): PermissionWithGroupName[] {

View file

@ -28,7 +28,9 @@ interface CreatePostProps {
}) => void
}
import { useLocalization } from '@/utils/hooks/useLocalization'
const CreatePost: React.FC<CreatePostProps> = ({ onCreatePost }) => {
const { translate } = useLocalization();
const [content, setContent] = useState('')
const [mediaType, setMediaType] = useState<'media' | 'poll' | null>(null)
const [mediaItems, setMediaItems] = useState<SocialMediaDto[]>([])
@ -164,7 +166,7 @@ const CreatePost: React.FC<CreatePostProps> = ({ onCreatePost }) => {
value={content}
onChange={(e) => setContent(e.target.value)}
onFocus={() => setIsExpanded(true)}
placeholder="Ne düşünüyorsunuz?"
placeholder={translate('::App.Platform.Intranet.SocialWall.CreatePost.Placeholder')}
className={classNames(
'w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 resize-none transition-all',
isExpanded ? 'min-h-[120px]' : 'min-h-[48px]'

View file

@ -1,4 +1,5 @@
import React from 'react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { FaExternalLinkAlt, FaMapMarkerAlt } from 'react-icons/fa'
interface LocationData {
@ -43,6 +44,7 @@ const LocationMap: React.FC<LocationMapProps> = ({
return `https://www.openstreetmap.org/export/embed.html?bbox=${lng - 0.01},${lat - 0.01},${lng + 0.01},${lat + 0.01}&layer=mapnik&marker=${lat},${lng}`
}
const { translate } = useLocalization();
return (
<div className={`relative rounded-lg overflow-hidden bg-gray-200 dark:bg-gray-700 ${className}`}>
{/* Map Container */}
@ -76,9 +78,9 @@ const LocationMap: React.FC<LocationMapProps> = ({
<button
onClick={handleOpenGoogleMaps}
className="absolute inset-0 w-full h-full cursor-pointer group"
aria-label="Google Maps'te aç"
aria-label={translate('::App.Platform.Intranet.SocialWall.LocationMap.OpenInGoogleMaps')}
>
<span className="sr-only">Google Maps'te </span>
<span className="sr-only">{translate('::App.Platform.Intranet.SocialWall.LocationMap.OpenInGoogleMaps')}</span>
</button>
{/* Hover Effect */}
@ -93,10 +95,10 @@ const LocationMap: React.FC<LocationMapProps> = ({
className="w-full flex items-center justify-center gap-2 px-4 py-2.5 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors"
>
<FaExternalLinkAlt className="w-5 h-5" />
<span>Google Maps'te </span>
<span>{translate('::App.Platform.Intranet.SocialWall.LocationMap.OpenInGoogleMaps')}</span>
</button>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-2 text-center">
Yol tarifi almak için tıklayın
{translate('::App.Platform.Intranet.SocialWall.LocationMap.ClickForDirections')}
</p>
</div>
)}

View file

@ -1,4 +1,5 @@
import React, { useState, useEffect, useRef } from 'react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { motion } from 'framer-motion'
import { FaTimes, FaSearch, FaMapMarkerAlt } from 'react-icons/fa'
import classNames from 'classnames'
@ -28,6 +29,7 @@ declare global {
}
const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) => {
const { translate } = useLocalization();
const [searchQuery, setSearchQuery] = useState('')
const [locations, setLocations] = useState<LocationData[]>([])
const [selectedLocation, setSelectedLocation] = useState<LocationData | null>(null)
@ -55,7 +57,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
}
if (!GOOGLE_API_KEY) {
setError('Google Maps API anahtarı bulunamadı. Lütfen .env dosyasına VITE_GOOGLE_MAPS_API_KEY ekleyin.')
setError(translate('::App.Platform.Intranet.SocialWall.LocationPicker.ApiKeyError'))
return
}
@ -92,7 +94,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
}
script.onerror = () => {
setError('Google Maps yüklenemedi. Lütfen internet bağlantınızı kontrol edin.')
setError(translate('::App.Platform.Intranet.SocialWall.LocationPicker.GoogleMapsLoadError'))
}
document.head.appendChild(script)
@ -142,7 +144,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
}
if (status !== window.google.maps.places.PlacesServiceStatus.OK) {
setError('Konum arama başarısız')
setError(translate('::App.Platform.Intranet.SocialWall.LocationPicker.SearchFailed'))
setIsLoading(false)
return
}
@ -189,7 +191,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
)
} catch (err) {
console.error('Location search error:', err)
setError('Konum arama sırasında bir hata oluştu')
setError(translate('::App.Platform.Intranet.SocialWall.LocationPicker.SearchError'))
setIsLoading(false)
}
}, 500) // 500ms debounce
@ -222,7 +224,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
>
{/* Header */}
<div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700">
<h2 className="text-xl font-bold text-gray-900 dark:text-white">Konum Ekle</h2>
<h2 className="text-xl font-bold text-gray-900 dark:text-white">{translate('::App.Platform.Intranet.SocialWall.LocationPicker.AddLocation')}</h2>
<button
onClick={onClose}
className="p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-full transition-colors"
@ -240,14 +242,14 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
type="text"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder="Konum ara..."
placeholder={translate('::App.Platform.Intranet.SocialWall.LocationPicker.SearchPlaceholder')}
disabled={!isGoogleLoaded}
className="w-full pl-10 pr-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:bg-gray-100 dark:disabled:bg-gray-600 disabled:cursor-not-allowed"
/>
</div>
{!isGoogleLoaded && (
<p className="text-xs text-gray-500 dark:text-gray-400 mt-2">
Google Maps yükleniyor...
{translate('::App.Platform.Intranet.SocialWall.LocationPicker.LoadingGoogleMaps')}
</p>
)}
</div>
@ -257,12 +259,12 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
{!isGoogleLoaded ? (
<div className="text-center py-12">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
<p className="text-gray-500 dark:text-gray-400">Google Maps yükleniyor...</p>
<p className="text-gray-500 dark:text-gray-400">{translate('::App.Platform.Intranet.SocialWall.LocationPicker.LoadingGoogleMaps')}</p>
</div>
) : isLoading ? (
<div className="text-center py-12">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
<p className="text-gray-500 dark:text-gray-400">Konumlar aranıyor...</p>
<p className="text-gray-500 dark:text-gray-400">{translate('::App.Platform.Intranet.SocialWall.LocationPicker.SearchingLocations')}</p>
</div>
) : error ? (
<div className="text-center py-12">
@ -273,17 +275,17 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
<div className="text-center py-12">
<FaSearch className="w-16 h-16 mx-auto mb-4 text-gray-400" />
<p className="text-gray-500 dark:text-gray-400">
Aramak istediğiniz konumu yazın
{translate('::App.Platform.Intranet.SocialWall.LocationPicker.TypeToSearch')}
</p>
<p className="text-sm text-gray-400 dark:text-gray-500 mt-2">
Örn: Taksim, İstanbul
{translate('::App.Platform.Intranet.SocialWall.LocationPicker.Example')}
</p>
</div>
) : locations.length === 0 ? (
<div className="text-center py-12">
<FaMapMarkerAlt className="w-16 h-16 mx-auto mb-4 text-gray-400" />
<p className="text-gray-500 dark:text-gray-400">
Konum bulunamadı. Farklı bir arama yapın.
{translate('::App.Platform.Intranet.SocialWall.LocationPicker.NotFound')}
</p>
</div>
) : (
@ -359,7 +361,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
</span>
</span>
) : (
<span>Bir konum seçin</span>
<span>{translate('::App.Platform.Intranet.SocialWall.LocationPicker.SelectLocation')}</span>
)}
</div>
<div className="flex gap-2">
@ -367,14 +369,14 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
onClick={onClose}
className="px-4 py-2 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded-lg transition-colors"
>
İptal
{translate('::App.Platform.Intranet.SocialWall.LocationPicker.Cancel')}
</button>
<button
onClick={handleConfirm}
disabled={!selectedLocation}
className="px-6 py-2 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed transition-colors"
>
Ekle
{translate('::App.Platform.Intranet.SocialWall.LocationPicker.Add')}
</button>
</div>
</div>

View file

@ -1,4 +1,5 @@
import React, { useState } from 'react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { motion } from 'framer-motion'
import { FaTimes, FaLink, FaUpload } from 'react-icons/fa'
import classNames from 'classnames'
@ -11,6 +12,7 @@ interface MediaManagerProps {
}
const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose }) => {
const { translate } = useLocalization();
const [activeTab, setActiveTab] = useState<'upload' | 'url'>('upload')
const [urlInput, setUrlInput] = useState('')
const [mediaType, setMediaType] = useState<'image' | 'video'>('image')
@ -58,7 +60,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
>
{/* Header */}
<div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700">
<h2 className="text-xl font-bold text-gray-900 dark:text-white">Medya Ekle</h2>
<h2 className="text-xl font-bold text-gray-900 dark:text-white">{translate('::App.Platform.Intranet.SocialWall.MediaManager.AddMedia')}</h2>
<button
onClick={onClose}
className="p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-full transition-colors"
@ -80,7 +82,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
>
<div className="flex items-center gap-2">
<FaUpload className="w-5 h-5" />
<span>Bilgisayarımdan Seç</span>
<span>{translate('::App.Platform.Intranet.SocialWall.MediaManager.SelectFromComputer')}</span>
</div>
</button>
<button
@ -94,7 +96,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
>
<div className="flex items-center gap-2">
<FaLink className="w-5 h-5" />
<span>URL ile Ekle</span>
<span>{translate('::App.Platform.Intranet.SocialWall.MediaManager.AddByUrl')}</span>
</div>
</button>
</div>
@ -107,10 +109,10 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
<div className="border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-8 text-center hover:border-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-colors cursor-pointer">
<FaUpload className="w-12 h-12 mx-auto mb-4 text-gray-400" />
<p className="text-gray-700 dark:text-gray-300 font-medium mb-1">
Dosya seçmek için tıklayın
{translate('::App.Platform.Intranet.SocialWall.MediaManager.ClickToSelectFile')}
</p>
<p className="text-sm text-gray-500 dark:text-gray-400">
Resim veya Video (PNG, JPG, GIF, MP4, MOV)
{translate('::App.Platform.Intranet.SocialWall.MediaManager.ImageOrVideoFormats')}
</p>
</div>
<input
@ -126,7 +128,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
<div>
<div className="mb-4">
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Medya Tipi
{translate('::App.Platform.Intranet.SocialWall.MediaManager.MediaType')}
</label>
<div className="flex gap-2">
<button
@ -138,7 +140,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
: 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'
)}
>
Resim
{translate('::App.Platform.Intranet.SocialWall.MediaManager.Image')}
</button>
<button
onClick={() => setMediaType('video')}
@ -149,7 +151,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
: 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'
)}
>
Video
{translate('::App.Platform.Intranet.SocialWall.MediaManager.Video')}
</button>
</div>
</div>
@ -159,7 +161,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
value={urlInput}
onChange={(e) => setUrlInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && handleUrlAdd()}
placeholder={`${mediaType === 'image' ? 'Resim' : 'Video'} URL'si girin`}
placeholder={mediaType === 'image' ? translate('::App.Platform.Intranet.SocialWall.MediaManager.EnterImageUrl') : translate('::App.Platform.Intranet.SocialWall.MediaManager.EnterVideoUrl')}
className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<button
@ -167,7 +169,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
disabled={!urlInput.trim()}
className="px-6 py-2 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed transition-colors"
>
Ekle
{translate('::App.Platform.Intranet.SocialWall.MediaManager.Add')}
</button>
</div>
</div>
@ -177,7 +179,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
{media.length > 0 && (
<div className="mt-6">
<h3 className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-3">
Eklenen Medyalar ({media.length})
{translate('::App.Platform.Intranet.SocialWall.MediaManager.AddedMedia')} ({media.length})
</h3>
<div className="grid grid-cols-4 gap-3">
{media.map((item) => (
@ -205,7 +207,7 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
<FaTimes className="w-4 h-4" />
</button>
<div className="absolute bottom-1 left-1 px-2 py-0.5 bg-black bg-opacity-70 text-white text-xs rounded">
{item.type === 'image' ? '📷' : '🎥'}
{item.type === 'image' ? translate('::App.Platform.Intranet.SocialWall.MediaManager.ImageIcon') : translate('::App.Platform.Intranet.SocialWall.MediaManager.VideoIcon')}
</div>
</div>
))}
@ -220,14 +222,14 @@ const MediaManager: React.FC<MediaManagerProps> = ({ media, onChange, onClose })
onClick={onClose}
className="px-4 py-2 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
>
İptal
{translate('::App.Platform.Intranet.SocialWall.MediaManager.Cancel')}
</button>
<button
onClick={onClose}
disabled={media.length === 0}
className="px-6 py-2 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed transition-colors"
>
Tamam ({media.length})
{translate('::App.Platform.Intranet.SocialWall.MediaManager.Done', { count: media.length })}
</button>
</div>
</motion.div>

View file

@ -1,4 +1,5 @@
import React, { useState, useRef, useEffect } from 'react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { motion, AnimatePresence } from 'framer-motion'
import classNames from 'classnames'
import dayjs from 'dayjs'
@ -28,6 +29,7 @@ interface PostItemProps {
}
const PostItem: React.FC<PostItemProps> = ({ post, onLike, onComment, onDelete, onVote }) => {
const { translate } = useLocalization();
const [showComments, setShowComments] = useState(false)
const [commentText, setCommentText] = useState('')
const [showAllImages, setShowAllImages] = useState(false)
@ -269,7 +271,7 @@ const PostItem: React.FC<PostItemProps> = ({ post, onLike, onComment, onDelete,
id: post.employee.id,
name: post.employee.name,
avatar: post.employee.avatar || 'https://i.pravatar.cc/150?img=1',
title: post.employee.jobPosition?.name || 'Çalışan',
title: post.employee.jobPosition?.name || translate('::App.Platform.Intranet.SocialWall.PostItem.Employee'),
email: post.employee.email,
phoneNumber: post.employee.phoneNumber,
department: post.employee.department?.name,
@ -285,7 +287,7 @@ const PostItem: React.FC<PostItemProps> = ({ post, onLike, onComment, onDelete,
{post.employee.name}
</h3>
<p className="text-sm text-gray-600 dark:text-gray-400">
{post.employee.jobPosition?.name || 'Çalışan'} {dayjs(post.creationTime).fromNow()}
{post.employee.jobPosition?.name || translate('::App.Platform.Intranet.SocialWall.PostItem.Employee')} {dayjs(post.creationTime).fromNow()}
</p>
</div>
</div>
@ -293,7 +295,7 @@ const PostItem: React.FC<PostItemProps> = ({ post, onLike, onComment, onDelete,
<button
onClick={() => onDelete(post.id)}
className="p-2 text-gray-500 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-full transition-colors"
title="Gönderiyi sil"
title={translate('::App.Platform.Intranet.SocialWall.PostItem.DeletePost')}
>
<FaTrash className="w-5 h-5" />
</button>
@ -357,7 +359,7 @@ const PostItem: React.FC<PostItemProps> = ({ post, onLike, onComment, onDelete,
type="text"
value={commentText}
onChange={(e) => setCommentText(e.target.value)}
placeholder="Yorum yazın..."
placeholder={translate('::App.Platform.Intranet.SocialWall.PostItem.CommentPlaceholder')}
className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-full bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<button
@ -391,7 +393,7 @@ const PostItem: React.FC<PostItemProps> = ({ post, onLike, onComment, onDelete,
id: comment.creator.id,
name: comment.creator.name,
avatar: comment.creator.avatar || 'https://i.pravatar.cc/150?img=1',
title: comment.creator.jobPosition?.name || 'Çalışan'
title: comment.creator.jobPosition?.name || translate('::App.Platform.Intranet.SocialWall.PostItem.Employee')
}}
position="bottom"
/>

View file

@ -1,7 +1,7 @@
import React from 'react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { motion } from 'framer-motion'
import { FaTimes, FaEye, FaClipboard } from 'react-icons/fa'
import dayjs from 'dayjs'
import { AnnouncementDto } from '@/proxy/intranet/models'
import useLocale from '@/utils/hooks/useLocale'
import { currentLocalDate } from '@/utils/dateUtils'
@ -12,6 +12,7 @@ interface AnnouncementDetailModalProps {
}
const AnnouncementDetailModal: React.FC<AnnouncementDetailModalProps> = ({ announcement, onClose }) => {
const { translate } = useLocalization();
const currentLocale = useLocale()
const getCategoryColor = (category: string) => {
const colors: Record<string, string> = {
@ -49,14 +50,14 @@ const AnnouncementDetailModal: React.FC<AnnouncementDetailModalProps> = ({ annou
<span
className={`px-3 py-1 text-xs font-medium rounded-full ${getCategoryColor(announcement.category)}`}
>
{announcement.category === 'general' && '📢 Genel'}
{announcement.category === 'hr' && '👥 İnsan Kaynakları'}
{announcement.category === 'it' && '💻 Bilgi Teknolojileri'}
{announcement.category === 'event' && '🎉 Etkinlik'}
{announcement.category === 'urgent' && '🚨 Acil'}
{announcement.category === 'general' && `📢 ${translate('::App.Platform.Intranet.AnnouncementDetailModal.Category.General')}`}
{announcement.category === 'hr' && `👥 ${translate('::App.Platform.Intranet.AnnouncementDetailModal.Category.HR')}`}
{announcement.category === 'it' && `💻 ${translate('::App.Platform.Intranet.AnnouncementDetailModal.Category.IT')}`}
{announcement.category === 'event' && `🎉 ${translate('::App.Platform.Intranet.AnnouncementDetailModal.Category.Event')}`}
{announcement.category === 'urgent' && `🚨 ${translate('::App.Platform.Intranet.AnnouncementDetailModal.Category.Urgent')}`}
</span>
{announcement.isPinned && (
<span className="text-yellow-500 text-sm">📌 Sabitlenmiş</span>
<span className="text-yellow-500 text-sm">📌 {translate('::App.Platform.Intranet.AnnouncementDetailModal.Pinned')}</span>
)}
</div>
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">
@ -89,7 +90,7 @@ const AnnouncementDetailModal: React.FC<AnnouncementDetailModalProps> = ({ annou
<span></span>
<span className="flex items-center gap-1">
<FaEye className="w-4 h-4" />
{announcement.viewCount} görüntülenme
{announcement.viewCount} {translate('::App.Platform.Intranet.AnnouncementDetailModal.Views')}
</span>
</div>
</div>
@ -120,7 +121,7 @@ const AnnouncementDetailModal: React.FC<AnnouncementDetailModalProps> = ({ annou
<div className="mt-6 pt-6 border-t border-gray-200 dark:border-gray-700">
<h3 className="text-sm font-semibold text-gray-900 dark:text-white mb-3 flex items-center gap-2">
<FaClipboard className="w-5 h-5" />
Ekler ({announcement.attachments.length})
{translate('::App.Platform.Intranet.AnnouncementDetailModal.Attachments')} ({announcement.attachments.length})
</h3>
<div className="space-y-2">
{announcement.attachments.map((attachment, idx) => (
@ -141,7 +142,7 @@ const AnnouncementDetailModal: React.FC<AnnouncementDetailModalProps> = ({ annou
</p>
</div>
<span className="text-sm text-blue-600 dark:text-blue-400">
İndir
{translate('::App.Platform.Intranet.AnnouncementDetailModal.Download')}
</span>
</a>
))}
@ -154,7 +155,7 @@ const AnnouncementDetailModal: React.FC<AnnouncementDetailModalProps> = ({ annou
announcement.departments.length > 0 && (
<div className="mt-6 pt-6 border-t border-gray-200 dark:border-gray-700">
<h3 className="text-sm font-semibold text-gray-900 dark:text-white mb-3">
Hedef Departmanlar
{translate('::App.Platform.Intranet.AnnouncementDetailModal.TargetDepartments')}
</h3>
<div className="flex flex-wrap gap-2">
{announcement.departments?.map((dept, idx) => (
@ -173,7 +174,7 @@ const AnnouncementDetailModal: React.FC<AnnouncementDetailModalProps> = ({ annou
{announcement.expiryDate && (
<div className="mt-6 pt-6 border-t border-gray-200 dark:border-gray-700">
<p className="text-sm text-gray-600 dark:text-gray-400">
<span className="font-medium">Son Geçerlilik Tarihi:</span>{' '}
<span className="font-medium">{translate('::App.Platform.Intranet.AnnouncementDetailModal.ExpiryDate')}:</span>{' '}
{currentLocalDate(announcement.expiryDate, currentLocale || 'tr')}
</p>
</div>
@ -186,7 +187,7 @@ const AnnouncementDetailModal: React.FC<AnnouncementDetailModalProps> = ({ annou
onClick={onClose}
className="w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors"
>
Kapat
{translate('::App.Platform.Intranet.AnnouncementDetailModal.Close')}
</button>
</div>
</motion.div>

View file

@ -1,4 +1,5 @@
import React from 'react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { motion } from 'framer-motion'
import { FaTimes } from 'react-icons/fa'
@ -8,6 +9,7 @@ interface ExpenseRequestModalProps {
}
const ExpenseRequestModal: React.FC<ExpenseRequestModalProps> = ({ onClose, onSubmit }) => {
const { translate } = useLocalization();
return (
<>
<motion.div
@ -27,7 +29,7 @@ const ExpenseRequestModal: React.FC<ExpenseRequestModalProps> = ({ onClose, onSu
>
<div className="p-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between sticky top-0 bg-white dark:bg-gray-800 z-10">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
Yeni Harcama Talebi
{translate('::App.Platform.Intranet.ExpenseRequestModal.Title')}
</h2>
<button
onClick={onClose}
@ -46,29 +48,29 @@ const ExpenseRequestModal: React.FC<ExpenseRequestModalProps> = ({ onClose, onSu
>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Harcama Kategorisi *
{translate('::App.Platform.Intranet.ExpenseRequestModal.Category')}
</label>
<select
required
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
>
<option value="">Seçiniz</option>
<option value="travel"> Seyahat</option>
<option value="meal">🍽 Yemek</option>
<option value="accommodation">🏨 Konaklama</option>
<option value="transport">🚗 Ulaşım</option>
<option value="other">📋 Diğer</option>
<option value="">{translate('::App.Platform.Intranet.ExpenseRequestModal.Select')}</option>
<option value="travel"> {translate('::App.Platform.Intranet.ExpenseRequestModal.Travel')}</option>
<option value="meal">🍽 {translate('::App.Platform.Intranet.ExpenseRequestModal.Meal')}</option>
<option value="accommodation">🏨 {translate('::App.Platform.Intranet.ExpenseRequestModal.Accommodation')}</option>
<option value="transport">🚗 {translate('::App.Platform.Intranet.ExpenseRequestModal.Transport')}</option>
<option value="other">📋 {translate('::App.Platform.Intranet.ExpenseRequestModal.Other')}</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
ıklama *
{translate('::App.Platform.Intranet.ExpenseRequestModal.Description')}
</label>
<input
type="text"
required
placeholder="Harcama açıklaması..."
placeholder={translate('::App.Platform.Intranet.ExpenseRequestModal.DescriptionPlaceholder')}
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
/>
</div>
@ -76,7 +78,7 @@ const ExpenseRequestModal: React.FC<ExpenseRequestModalProps> = ({ onClose, onSu
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Tutar () *
{translate('::App.Platform.Intranet.ExpenseRequestModal.Amount')}
</label>
<input
type="number"
@ -89,7 +91,7 @@ const ExpenseRequestModal: React.FC<ExpenseRequestModalProps> = ({ onClose, onSu
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Tarih *
{translate('::App.Platform.Intranet.ExpenseRequestModal.Date')}
</label>
<input
type="date"
@ -101,11 +103,11 @@ const ExpenseRequestModal: React.FC<ExpenseRequestModalProps> = ({ onClose, onSu
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Not
{translate('::App.Platform.Intranet.ExpenseRequestModal.Note')}
</label>
<textarea
rows={3}
placeholder="Ek bilgi (opsiyonel)..."
placeholder={translate('::App.Platform.Intranet.ExpenseRequestModal.NotePlaceholder')}
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
/>
</div>
@ -116,13 +118,13 @@ const ExpenseRequestModal: React.FC<ExpenseRequestModalProps> = ({ onClose, onSu
onClick={onClose}
className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
>
İptal
{translate('::App.Platform.Intranet.ExpenseRequestModal.Cancel')}
</button>
<button
type="submit"
className="flex-1 px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-white rounded-lg transition-colors"
>
Gönder
{translate('::App.Platform.Intranet.ExpenseRequestModal.Submit')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
import React from 'react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { motion } from 'framer-motion'
import { FaTimes } from 'react-icons/fa'
@ -8,6 +9,7 @@ interface LeaveRequestModalProps {
}
const LeaveRequestModal: React.FC<LeaveRequestModalProps> = ({ onClose, onSubmit }) => {
const { translate } = useLocalization();
return (
<>
<motion.div
@ -27,7 +29,7 @@ const LeaveRequestModal: React.FC<LeaveRequestModalProps> = ({ onClose, onSubmit
>
<div className="p-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between sticky top-0 bg-white dark:bg-gray-800 z-10">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
Yeni İzin Talebi
{translate('::App.Platform.Intranet.LeaveRequestModal.Title')}
</h2>
<button
onClick={onClose}
@ -46,24 +48,24 @@ const LeaveRequestModal: React.FC<LeaveRequestModalProps> = ({ onClose, onSubmit
>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
İzin Türü *
{translate('::App.Platform.Intranet.LeaveRequestModal.LeaveType')}
</label>
<select
required
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
>
<option value="">Seçiniz</option>
<option value="annual">🏖 Yıllık İzin</option>
<option value="sick">🏥 Hastalık İzni</option>
<option value="unpaid">💼 Ücretsiz İzin</option>
<option value="other">📋 Diğer</option>
<option value="">{translate('::App.Platform.Intranet.LeaveRequestModal.Select')}</option>
<option value="annual">🏖 {translate('::App.Platform.Intranet.LeaveRequestModal.AnnualLeave')}</option>
<option value="sick">🏥 {translate('::App.Platform.Intranet.LeaveRequestModal.SickLeave')}</option>
<option value="unpaid">💼 {translate('::App.Platform.Intranet.LeaveRequestModal.UnpaidLeave')}</option>
<option value="other">📋 {translate('::App.Platform.Intranet.LeaveRequestModal.Other')}</option>
</select>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Başlangıç Tarihi *
{translate('::App.Platform.Intranet.LeaveRequestModal.StartDate')}
</label>
<input
type="date"
@ -73,7 +75,7 @@ const LeaveRequestModal: React.FC<LeaveRequestModalProps> = ({ onClose, onSubmit
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Bitiş Tarihi *
{translate('::App.Platform.Intranet.LeaveRequestModal.EndDate')}
</label>
<input
type="date"
@ -85,12 +87,12 @@ const LeaveRequestModal: React.FC<LeaveRequestModalProps> = ({ onClose, onSubmit
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
ıklama *
{translate('::App.Platform.Intranet.LeaveRequestModal.Description')}
</label>
<textarea
required
rows={3}
placeholder="İzin sebebinizi yazınız..."
placeholder={translate('::App.Platform.Intranet.LeaveRequestModal.ReasonPlaceholder')}
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
/>
</div>
@ -101,13 +103,13 @@ const LeaveRequestModal: React.FC<LeaveRequestModalProps> = ({ onClose, onSubmit
onClick={onClose}
className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
>
İptal
{translate('::App.Platform.Intranet.LeaveRequestModal.Cancel')}
</button>
<button
type="submit"
className="flex-1 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors"
>
Gönder
{translate('::App.Platform.Intranet.LeaveRequestModal.Submit')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
import React from 'react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { motion } from 'framer-motion'
import { FaTimes } from 'react-icons/fa'
@ -8,6 +9,7 @@ interface OvertimeRequestModalProps {
}
const OvertimeRequestModal: React.FC<OvertimeRequestModalProps> = ({ onClose, onSubmit }) => {
const { translate } = useLocalization();
return (
<>
<motion.div
@ -27,7 +29,7 @@ const OvertimeRequestModal: React.FC<OvertimeRequestModalProps> = ({ onClose, on
>
<div className="p-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between sticky top-0 bg-white dark:bg-gray-800 z-10">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
Yeni Mesai Talebi
{translate('::App.Platform.Intranet.OvertimeRequestModal.Title')}
</h2>
<button
onClick={onClose}
@ -46,7 +48,7 @@ const OvertimeRequestModal: React.FC<OvertimeRequestModalProps> = ({ onClose, on
>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Mesai Tarihi *
{translate('::App.Platform.Intranet.OvertimeRequestModal.Date')}
</label>
<input
type="date"
@ -58,7 +60,7 @@ const OvertimeRequestModal: React.FC<OvertimeRequestModalProps> = ({ onClose, on
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Başlangıç Saati *
{translate('::App.Platform.Intranet.OvertimeRequestModal.StartTime')}
</label>
<input
type="time"
@ -68,7 +70,7 @@ const OvertimeRequestModal: React.FC<OvertimeRequestModalProps> = ({ onClose, on
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Bitiş Saati *
{translate('::App.Platform.Intranet.OvertimeRequestModal.EndTime')}
</label>
<input
type="time"
@ -80,12 +82,12 @@ const OvertimeRequestModal: React.FC<OvertimeRequestModalProps> = ({ onClose, on
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
ıklama *
{translate('::App.Platform.Intranet.OvertimeRequestModal.Description')}
</label>
<textarea
required
rows={3}
placeholder="Mesai sebebinizi yazınız..."
placeholder={translate('::App.Platform.Intranet.OvertimeRequestModal.ReasonPlaceholder')}
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
/>
</div>
@ -96,13 +98,13 @@ const OvertimeRequestModal: React.FC<OvertimeRequestModalProps> = ({ onClose, on
onClick={onClose}
className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
>
İptal
{translate('::App.Platform.Intranet.OvertimeRequestModal.Cancel')}
</button>
<button
type="submit"
className="flex-1 px-4 py-2 bg-orange-600 hover:bg-orange-700 text-white rounded-lg transition-colors"
>
Gönder
{translate('::App.Platform.Intranet.OvertimeRequestModal.Submit')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
import React from 'react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { motion } from 'framer-motion'
import { FaTimes } from 'react-icons/fa'
@ -8,6 +9,7 @@ interface ReservationRequestModalProps {
}
const ReservationRequestModal: React.FC<ReservationRequestModalProps> = ({ onClose, onSubmit }) => {
const { translate } = useLocalization();
return (
<>
<motion.div
@ -27,7 +29,7 @@ const ReservationRequestModal: React.FC<ReservationRequestModalProps> = ({ onClo
>
<div className="p-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between sticky top-0 bg-white dark:bg-gray-800 z-10">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
Yeni Rezervasyon Talebi
{translate('::App.Platform.Intranet.ReservationRequestModal.Title')}
</h2>
<button
onClick={onClose}
@ -46,27 +48,27 @@ const ReservationRequestModal: React.FC<ReservationRequestModalProps> = ({ onClo
>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Rezervasyon Türü *
{translate('::App.Platform.Intranet.ReservationRequestModal.Type')}
</label>
<select
required
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
>
<option value="">Seçiniz</option>
<option value="room">🏢 Toplantı Odası</option>
<option value="vehicle">🚗 Şirket Aracı</option>
<option value="equipment"> Ekipman</option>
<option value="">{translate('::App.Platform.Intranet.ReservationRequestModal.Select')}</option>
<option value="room">🏢 {translate('::App.Platform.Intranet.ReservationRequestModal.Room')}</option>
<option value="vehicle">🚗 {translate('::App.Platform.Intranet.ReservationRequestModal.Vehicle')}</option>
<option value="equipment"> {translate('::App.Platform.Intranet.ReservationRequestModal.Equipment')}</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Kaynak Adı *
{translate('::App.Platform.Intranet.ReservationRequestModal.ResourceName')}
</label>
<input
type="text"
required
placeholder="Örn: Toplantı Salonu A, Şirket Aracı - Plaka, Kamera Seti..."
placeholder={translate('::App.Platform.Intranet.ReservationRequestModal.ResourceNamePlaceholder')}
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
/>
</div>
@ -74,7 +76,7 @@ const ReservationRequestModal: React.FC<ReservationRequestModalProps> = ({ onClo
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Başlangıç Tarihi *
{translate('::App.Platform.Intranet.ReservationRequestModal.StartDate')}
</label>
<input
type="datetime-local"
@ -84,7 +86,7 @@ const ReservationRequestModal: React.FC<ReservationRequestModalProps> = ({ onClo
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Bitiş Tarihi *
{translate('::App.Platform.Intranet.ReservationRequestModal.EndDate')}
</label>
<input
type="datetime-local"
@ -96,42 +98,42 @@ const ReservationRequestModal: React.FC<ReservationRequestModalProps> = ({ onClo
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Amaç *
{translate('::App.Platform.Intranet.ReservationRequestModal.Purpose')}
</label>
<input
type="text"
required
placeholder="Rezervasyon amacını belirtiniz..."
placeholder={translate('::App.Platform.Intranet.ReservationRequestModal.PurposePlaceholder')}
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Katılımcı Sayısı
{translate('::App.Platform.Intranet.ReservationRequestModal.ParticipantCount')}
</label>
<input
type="number"
min="1"
placeholder="Toplantı odası için katılımcı sayısı (opsiyonel)"
placeholder={translate('::App.Platform.Intranet.ReservationRequestModal.ParticipantCountPlaceholder')}
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Notlar
{translate('::App.Platform.Intranet.ReservationRequestModal.Notes')}
</label>
<textarea
rows={3}
placeholder="Ek bilgi veya özel istekler (opsiyonel)..."
placeholder={translate('::App.Platform.Intranet.ReservationRequestModal.NotesPlaceholder')}
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
/>
</div>
<div className="bg-blue-50 dark:bg-blue-900/20 rounded-lg p-3">
<p className="text-sm text-blue-700 dark:text-blue-300">
Rezervasyon talebiniz yönetici onayına sunulacaktır.
{translate('::App.Platform.Intranet.ReservationRequestModal.Info')}
</p>
</div>
@ -141,13 +143,13 @@ const ReservationRequestModal: React.FC<ReservationRequestModalProps> = ({ onClo
onClick={onClose}
className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
>
İptal
{translate('::App.Platform.Intranet.ReservationRequestModal.Cancel')}
</button>
<button
type="submit"
className="flex-1 px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded-lg transition-colors"
>
Gönder
{translate('::App.Platform.Intranet.ReservationRequestModal.Submit')}
</button>
</div>
</form>

View file

@ -9,7 +9,9 @@ interface SurveyModalProps {
onSubmit: (answers: SurveyAnswerDto[]) => void
}
import { useLocalization } from '@/utils/hooks/useLocalization'
const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit }) => {
const { translate } = useLocalization();
const [answers, setAnswers] = useState<{ [questionId: string]: any }>({})
const [errors, setErrors] = useState<{ [questionId: string]: string }>({})
@ -33,7 +35,7 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
survey.questions.forEach((question) => {
if (question.isRequired && (!answers[question.id] || answers[question.id] === '')) {
newErrors[question.id] = 'Bu alan zorunludur'
newErrors[question.id] = translate('::App.Platform.Intranet.SurveyModal.RequiredField')
}
})
@ -159,7 +161,7 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
className={`w-full px-4 py-2 border rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 ${
hasError ? 'border-red-500' : 'border-gray-300 dark:border-gray-600'
}`}
placeholder="Cevabınızı yazın..."
placeholder={translate('::App.Platform.Intranet.SurveyModal.AnswerPlaceholder')}
/>
{hasError && (
<p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>
@ -180,7 +182,7 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
className={`w-full px-4 py-2 border rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 ${
hasError ? 'border-red-500' : 'border-gray-300 dark:border-gray-600'
}`}
placeholder="Yorumlarınızı buraya yazabilirsiniz..."
placeholder={translate('::App.Platform.Intranet.SurveyModal.CommentPlaceholder')}
/>
{hasError && (
<p className="text-sm text-red-600 dark:text-red-400">{errors[question.id]}</p>
@ -254,13 +256,13 @@ const SurveyModal: React.FC<SurveyModalProps> = ({ survey, onClose, onSubmit })
onClick={onClose}
className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
>
İptal
{translate('::App.Platform.Intranet.SurveyModal.Cancel')}
</button>
<button
type="submit"
className="flex-1 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors"
>
Anketi Gönder
{translate('::App.Platform.Intranet.SurveyModal.Submit')}
</button>
</div>
</form>

View file

@ -3,6 +3,7 @@ import { FaKey, FaPlus } from 'react-icons/fa'
import { ReservationDto } from '@/proxy/intranet/models'
import useLocale from '@/utils/hooks/useLocale'
import { currentLocalDate } from '@/utils/dateUtils'
import { useLocalization } from '@/utils/hooks/useLocalization'
interface ActiveReservationsProps {
reservations: ReservationDto[]
@ -14,13 +15,14 @@ const ActiveReservations: React.FC<ActiveReservationsProps> = ({
onNewReservation,
}) => {
const currentLocale = useLocale()
const { translate } = useLocalization()
return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4 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">
<FaKey className="w-5 h-5" />
Aktif Rezervasyonlar
{translate('::App.Platform.Intranet.Widgets.ActiveReservations.Title')}
</h2>
</div>
<div className="p-4 space-y-3">
@ -52,7 +54,7 @@ const ActiveReservations: React.FC<ActiveReservationsProps> = ({
))}
{reservations.filter((r) => r.status === 'approved').length === 0 && (
<p className="text-sm text-gray-500 dark:text-gray-400 text-center py-4">
Aktif rezervasyon yok
{translate('::App.Platform.Intranet.Widgets.ActiveReservations.NoActive')}
</p>
)}
@ -61,7 +63,7 @@ const ActiveReservations: React.FC<ActiveReservationsProps> = ({
className="w-full mt-3 px-4 py-2 bg-green-600 hover:bg-green-700 text-white text-sm rounded-lg transition-colors flex items-center justify-center gap-2"
>
<FaPlus className="w-4 h-4" />
Yeni Rezervasyon
{translate('::App.Platform.Intranet.Widgets.ActiveReservations.NewReservation')}
</button>
</div>
</div>

View file

@ -4,6 +4,7 @@ import dayjs from 'dayjs'
import { SurveyDto } from '@/proxy/intranet/models'
import useLocale from '@/utils/hooks/useLocale'
import { currentLocalDate } from '@/utils/dateUtils'
import { useLocalization } from '@/utils/hooks/useLocalization'
interface ActiveSurveysProps {
surveys?: SurveyDto[]
@ -12,6 +13,7 @@ interface ActiveSurveysProps {
const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ surveys, onTakeSurvey }) => {
const currentLocale = useLocale()
const { translate } = useLocalization()
return (
<div className="bg-gradient-to-br from-white to-gray-50 dark:from-gray-800 dark:to-gray-850 rounded-xl shadow-lg border border-gray-200/50 dark:border-gray-700/50 overflow-hidden">
@ -20,7 +22,7 @@ const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ surveys, onTakeSurvey })
<div className="p-4 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">
<FaClipboardCheck className="w-5 h-5" />
Aktif Anketler
{translate('::App.Platform.Intranet.Widgets.ActiveSurveys.Title')}
</h2>
</div>
@ -53,7 +55,7 @@ const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ surveys, onTakeSurvey })
: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300'
}`}
>
{daysLeft > 0 ? `${daysLeft} gün` : 'Son gün'}
{daysLeft > 0 ? translate('::App.Platform.Intranet.Widgets.ActiveSurveys.DaysLeft', { count: daysLeft }) : translate('::App.Platform.Intranet.Widgets.ActiveSurveys.LastDay')}
</div>
</div>
@ -64,7 +66,7 @@ const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ surveys, onTakeSurvey })
<FaQuestionCircle className="w-3 h-3 text-blue-600 dark:text-blue-400" />
</div>
<div>
<p className="text-xs text-gray-500 dark:text-gray-400">Sorular</p>
<p className="text-xs text-gray-500 dark:text-gray-400">{translate('::App.Platform.Intranet.Widgets.ActiveSurveys.Questions')}</p>
<p className="font-semibold text-gray-900 dark:text-white">
{survey.questions.length}
</p>
@ -76,7 +78,7 @@ const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ surveys, onTakeSurvey })
<FaUsers className="w-3 h-3 text-green-600 dark:text-green-400" />
</div>
<div>
<p className="text-xs text-gray-500 dark:text-gray-400">Yanıtlar</p>
<p className="text-xs text-gray-500 dark:text-gray-400">{translate('::App.Platform.Intranet.Widgets.ActiveSurveys.Responses')}</p>
<p className="font-semibold text-gray-900 dark:text-white">
{survey.responses}
</p>
@ -88,7 +90,7 @@ const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ surveys, onTakeSurvey })
<FaClock className="w-3 h-3 text-purple-600 dark:text-purple-400" />
</div>
<div>
<p className="text-xs text-gray-500 dark:text-gray-400">Süre</p>
<p className="text-xs text-gray-500 dark:text-gray-400">{translate('::App.Platform.Intranet.Widgets.ActiveSurveys.Duration')}</p>
<p className="font-semibold text-gray-900 dark:text-white">~5dk</p>
</div>
</div>
@ -97,7 +99,7 @@ const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ surveys, onTakeSurvey })
{/* Progress Bar */}
<div className="mb-4">
<div className="flex justify-between text-xs mb-1">
<span className="text-gray-600 dark:text-gray-400">Tamamlanma oranı</span>
<span className="text-gray-600 dark:text-gray-400">{translate('::App.Platform.Intranet.Widgets.ActiveSurveys.CompletionRate')}</span>
<span className="text-gray-800 dark:text-gray-200 font-medium">
{Math.round((survey.responses / 100) * 100)}%
</span>
@ -118,7 +120,7 @@ const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ surveys, onTakeSurvey })
{/* Action Button */}
<button className="w-full flex items-center justify-center gap-2 px-4 py-3 bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700 text-white text-sm font-medium rounded-lg transition-all duration-300 transform group-hover:scale-[1.02] shadow-sm hover:shadow-md">
Anketi Doldur
{translate('::App.Platform.Intranet.Widgets.ActiveSurveys.FillSurvey')}
<FaArrowRight className="w-3 h-3 transition-transform group-hover:translate-x-1" />
</button>
</div>
@ -132,10 +134,10 @@ const ActiveSurveys: React.FC<ActiveSurveysProps> = ({ surveys, onTakeSurvey })
<FaClipboardCheck className="w-8 h-8 text-gray-400" />
</div>
<h3 className="text-lg font-medium text-gray-900 dark:text-white mb-2">
Aktif anket bulunmuyor
{translate('::App.Platform.Intranet.Widgets.ActiveSurveys.NoActive')}
</h3>
<p className="text-sm text-gray-500 dark:text-gray-400">
Yeni anketler eklendiğinde burada görünecektir.
{translate('::App.Platform.Intranet.Widgets.ActiveSurveys.WillAppearHere')}
</p>
</div>
)}

View file

@ -2,6 +2,7 @@ import React from 'react'
import { FaBell, FaClipboardCheck, FaEye } from 'react-icons/fa'
import dayjs from 'dayjs'
import { AnnouncementDto } from '@/proxy/intranet/models'
import { useLocalization } from '@/utils/hooks/useLocalization'
interface AnnouncementsProps {
announcements: AnnouncementDto[]
@ -10,6 +11,7 @@ interface AnnouncementsProps {
const Announcements: React.FC<AnnouncementsProps> = ({ announcements, onAnnouncementClick }) => {
const pinnedAnnouncements = announcements.filter((a) => a.isPinned).slice(0, 3)
const { translate } = useLocalization();
const getCategoryColor = (category: string) => {
const colors: Record<string, string> = {
@ -28,7 +30,7 @@ const Announcements: React.FC<AnnouncementsProps> = ({ announcements, onAnnounce
<div className="flex items-center justify-between">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white flex items-center gap-2">
<FaBell className="w-5 h-5" />
Önemli Duyurular
{translate('::App.Platform.Intranet.Widgets.Announcements.Title')}
</h2>
</div>
</div>
@ -53,7 +55,7 @@ const Announcements: React.FC<AnnouncementsProps> = ({ announcements, onAnnounce
<span
className={`px-2 py-1 text-xs rounded-full ${getCategoryColor(announcement.category)}`}
>
{announcement.category}
{translate(`::App.Platform.Intranet.Widgets.Announcements.Category.${announcement.category.charAt(0).toUpperCase() + announcement.category.slice(1)}`, announcement.category)}
</span>
</div>
<p className="text-sm text-gray-600 dark:text-gray-400 line-clamp-2">
@ -80,10 +82,10 @@ const Announcements: React.FC<AnnouncementsProps> = ({ announcements, onAnnounce
<FaClipboardCheck className="w-8 h-8 text-gray-400" />
</div>
<h3 className="text-lg font-medium text-gray-900 dark:text-white mb-2">
Aktif duyuru bulunmuyor
{translate('::App.Platform.Intranet.Widgets.Announcements.NoActive')}
</h3>
<p className="text-sm text-gray-500 dark:text-gray-400">
Yeni duyurular eklendiğinde burada görünecektir.
{translate('::App.Platform.Intranet.Widgets.Announcements.WillAppearHere')}
</p>
</div>
)}

View file

@ -1,6 +1,7 @@
import React from 'react'
import { FaDollarSign, FaPlus } from 'react-icons/fa'
import { ExpensesDto } from '@/proxy/intranet/models'
import { useLocalization } from '@/utils/hooks/useLocalization'
interface ExpenseManagementProps {
expenses: ExpensesDto
@ -8,23 +9,24 @@ interface ExpenseManagementProps {
}
const ExpenseManagement: React.FC<ExpenseManagementProps> = ({ expenses, onNewExpense }) => {
const { translate } = useLocalization();
return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4 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">
<FaDollarSign className="w-5 h-5" />
Harcama Yönetimi
{translate('::App.Platform.Intranet.Widgets.ExpenseManagement.Title')}
</h2>
</div>
<div className="p-4 space-y-3">
{/* Harcama özeti */}
<div className="p-3 bg-emerald-50 dark:bg-emerald-900/20 rounded-lg border border-emerald-200 dark:border-emerald-800 mb-4">
<p className="text-xs text-gray-600 dark:text-gray-400">Bu Ay Toplam</p>
<p className="text-xs text-gray-600 dark:text-gray-400">{translate('::App.Platform.Intranet.Widgets.ExpenseManagement.ThisMonthTotal')}</p>
<p className="text-2xl font-bold text-emerald-600 dark:text-emerald-400">
{expenses.totalRequested.toLocaleString('tr-TR')}
</p>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
{expenses.totalApproved.toLocaleString('tr-TR')} onaylandı
{expenses.totalApproved.toLocaleString('tr-TR')} {translate('::App.Platform.Intranet.Widgets.ExpenseManagement.Approved')}
</p>
</div>
@ -63,10 +65,10 @@ const ExpenseManagement: React.FC<ExpenseManagementProps> = ({ expenses, onNewEx
}`}
>
{expense.status === 'approved'
? 'Onaylandı'
? translate('::App.Platform.Intranet.Widgets.ExpenseManagement.Status.Approved')
: expense.status === 'pending'
? 'Bekliyor'
: 'Reddedildi'}
? translate('::App.Platform.Intranet.Widgets.ExpenseManagement.Status.Pending')
: translate('::App.Platform.Intranet.Widgets.ExpenseManagement.Status.Rejected')}
</span>
</div>
</div>
@ -78,7 +80,7 @@ const ExpenseManagement: React.FC<ExpenseManagementProps> = ({ expenses, onNewEx
className="w-full mt-3 px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-white text-sm rounded-lg transition-colors flex items-center justify-center gap-2"
>
<FaPlus className="w-4 h-4" />
Yeni Harcama Talebi
{translate('::App.Platform.Intranet.Widgets.ExpenseManagement.NewExpense')}
</button>
</div>
</div>

View file

@ -4,6 +4,7 @@ import { LeaveDto } from '@/proxy/intranet/models'
import useLocale from '@/utils/hooks/useLocale'
import { currentLocalDate } from '@/utils/dateUtils'
import { LeaveStatusEnum, LeaveTypeEnum } from '@/types/intranet'
import { useLocalization } from '@/utils/hooks/useLocalization'
interface LeaveManagementProps {
leaves: LeaveDto[]
@ -12,25 +13,26 @@ interface LeaveManagementProps {
const LeaveManagement: React.FC<LeaveManagementProps> = ({ leaves, onNewLeave }) => {
const currentLocale = useLocale()
const { translate } = useLocalization();
return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4 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">
<FaCalendarAlt className="w-5 h-5" />
İzin Yönetimi
{translate('::App.Platform.Intranet.Widgets.LeaveManagement.Title')}
</h2>
</div>
<div className="p-4 space-y-3">
{/* İzin bakiye özeti */}
<div className="grid grid-cols-2 gap-2 mb-4">
<div className="p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800">
<p className="text-xs text-gray-600 dark:text-gray-400">Yıllık İzin</p>
<p className="text-lg font-bold text-blue-600 dark:text-blue-400">12 gün</p>
<p className="text-xs text-gray-600 dark:text-gray-400">{translate('::App.Platform.Intranet.Widgets.LeaveManagement.AnnualLeave')}</p>
<p className="text-lg font-bold text-blue-600 dark:text-blue-400">12 {translate('::App.Platform.Intranet.Widgets.LeaveManagement.Day')}</p>
</div>
<div className="p-3 bg-green-50 dark:bg-green-900/20 rounded-lg border border-green-200 dark:border-green-800">
<p className="text-xs text-gray-600 dark:text-gray-400">Hastalık İzni</p>
<p className="text-lg font-bold text-green-600 dark:text-green-400">8 gün</p>
<p className="text-xs text-gray-600 dark:text-gray-400">{translate('::App.Platform.Intranet.Widgets.LeaveManagement.SickLeave')}</p>
<p className="text-lg font-bold text-green-600 dark:text-green-400">8 {translate('::App.Platform.Intranet.Widgets.LeaveManagement.Day')}</p>
</div>
</div>
@ -44,13 +46,13 @@ const LeaveManagement: React.FC<LeaveManagementProps> = ({ leaves, onNewLeave })
<div className="flex items-start justify-between mb-1">
<h4 className="text-sm font-medium text-gray-900 dark:text-white">
{leave.leaveType === LeaveTypeEnum.Annual
? '🏖️ Yıllık'
? `🏖️ ${translate('::App.Platform.Intranet.Widgets.LeaveManagement.Annual')}`
: leave.leaveType === LeaveTypeEnum.Sick
? '🏥 Hastalık'
? `🏥 ${translate('::App.Platform.Intranet.Widgets.LeaveManagement.Sick')}`
: leave.leaveType === LeaveTypeEnum.Unpaid
? '💼 Ücretsiz'
: '📋 Diğer'}{' '}
İzin
? `💼 ${translate('::App.Platform.Intranet.Widgets.LeaveManagement.Unpaid')}`
: `📋 ${translate('::App.Platform.Intranet.Widgets.LeaveManagement.Other')}`}{' '}
{translate('::App.Platform.Intranet.Widgets.LeaveManagement.Leave')}
</h4>
<span
className={`text-xs px-2 py-1 rounded-full ${
@ -62,15 +64,15 @@ const LeaveManagement: React.FC<LeaveManagementProps> = ({ leaves, onNewLeave })
}`}
>
{leave.status === LeaveStatusEnum.Approved
? 'Onaylandı'
? translate('::App.Platform.Intranet.Widgets.LeaveManagement.Status.Approved')
: leave.status === LeaveStatusEnum.Pending
? 'Bekliyor'
: 'Reddedildi'}
? translate('::App.Platform.Intranet.Widgets.LeaveManagement.Status.Pending')
: translate('::App.Platform.Intranet.Widgets.LeaveManagement.Status.Rejected')}
</span>
</div>
<p className="text-xs text-gray-600 dark:text-gray-400">
{currentLocalDate(leave.startDate, currentLocale || 'tr')} - {currentLocalDate(leave.endDate, currentLocale || 'tr')}{' '}
({leave.totalDays} gün)
({leave.totalDays} {translate('::App.Platform.Intranet.Widgets.LeaveManagement.Day')})
</p>
</div>
))}
@ -81,7 +83,7 @@ const LeaveManagement: React.FC<LeaveManagementProps> = ({ leaves, onNewLeave })
className="w-full mt-3 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm rounded-lg transition-colors flex items-center justify-center gap-2"
>
<FaPlus className="w-4 h-4" />
Yeni İzin Talebi
{translate('::App.Platform.Intranet.Widgets.LeaveManagement.NewLeaveRequest')}
</button>
</div>
</div>

View file

@ -6,11 +6,13 @@ import { Badge } from '@/components/ui'
import { MealDto } from '@/proxy/intranet/models'
import useLocale from '@/utils/hooks/useLocale'
import { currentLocalDate } from '@/utils/dateUtils'
import { useLocalization } from '@/utils/hooks/useLocalization'
dayjs.extend(isBetween)
const MealWeeklyMenu: React.FC<{ meals: MealDto[] }> = ({ meals }) => {
const currentLocale = useLocale()
const { translate } = useLocalization();
return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
@ -18,7 +20,7 @@ const MealWeeklyMenu: React.FC<{ meals: MealDto[] }> = ({ meals }) => {
<div className="flex items-center justify-between">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white flex items-center gap-2">
<FaUtensils className="w-5 h-5" />
Haftalık Menü
{translate('::App.Platform.Intranet.Widgets.MealWeeklyMenu.Title')}
</h2>
</div>
</div>
@ -40,7 +42,7 @@ const MealWeeklyMenu: React.FC<{ meals: MealDto[] }> = ({ meals }) => {
</h3>
{isToday && (
<span className="text-xs bg-orange-500 text-white px-2 py-0.5 rounded-full">
Bugün
{translate('::App.Platform.Intranet.Widgets.MealWeeklyMenu.Today')}
</span>
)}
</div>
@ -67,7 +69,7 @@ const MealWeeklyMenu: React.FC<{ meals: MealDto[] }> = ({ meals }) => {
</div>
<div className="space-y-1">
<p className="text-xs text-gray-500 dark:text-gray-400">
Haftalık menü henüz hazırlanmamış. Lütfen daha sonra tekrar kontrol edin.
{translate('::App.Platform.Intranet.Widgets.MealWeeklyMenu.NotReady')}
</p>
</div>
</div>

View file

@ -4,6 +4,7 @@ import { OvertimeDto } from '@/proxy/intranet/models'
import useLocale from '@/utils/hooks/useLocale'
import { currentLocalDate } from '@/utils/dateUtils'
import { LeaveStatusEnum } from '@/types/intranet'
import { useLocalization } from '@/utils/hooks/useLocalization'
interface OvertimeManagementProps {
overtimes: OvertimeDto[]
@ -12,21 +13,22 @@ interface OvertimeManagementProps {
const OvertimeManagement: React.FC<OvertimeManagementProps> = ({ overtimes, onNewOvertime }) => {
const currentLocale = useLocale()
const { translate } = useLocalization();
return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4 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">
<FaClock className="w-5 h-5" />
Mesai Yönetimi
{translate('::App.Platform.Intranet.Widgets.OvertimeManagement.Title')}
</h2>
</div>
<div className="p-4 space-y-3">
{/* Mesai özeti */}
<div className="p-3 bg-orange-50 dark:bg-orange-900/20 rounded-lg border border-orange-200 dark:border-orange-800 mb-4">
<p className="text-xs text-gray-600 dark:text-gray-400">Bu Ay Toplam</p>
<p className="text-2xl font-bold text-orange-600 dark:text-orange-400">24 saat</p>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">20 onaylandı, 4 bekliyor</p>
<p className="text-xs text-gray-600 dark:text-gray-400">{translate('::App.Platform.Intranet.Widgets.OvertimeManagement.ThisMonthTotal')}</p>
<p className="text-2xl font-bold text-orange-600 dark:text-orange-400">24 {translate('::App.Platform.Intranet.Widgets.OvertimeManagement.Hour')}</p>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">20 {translate('::App.Platform.Intranet.Widgets.OvertimeManagement.Status.Approved')}, 4 {translate('::App.Platform.Intranet.Widgets.OvertimeManagement.Status.Pending')}</p>
</div>
{/* Son mesai talepleri */}
@ -50,10 +52,10 @@ const OvertimeManagement: React.FC<OvertimeManagementProps> = ({ overtimes, onNe
}`}
>
{overtime.status === LeaveStatusEnum.Approved
? 'Onaylandı'
? translate('::App.Platform.Intranet.Widgets.OvertimeManagement.Status.Approved')
: overtime.status === LeaveStatusEnum.Pending
? 'Bekliyor'
: 'Reddedildi'}
? translate('::App.Platform.Intranet.Widgets.OvertimeManagement.Status.Pending')
: translate('::App.Platform.Intranet.Widgets.OvertimeManagement.Status.Rejected')}
</span>
</div>
<p className="text-xs text-gray-600 dark:text-gray-400">
@ -68,7 +70,7 @@ const OvertimeManagement: React.FC<OvertimeManagementProps> = ({ overtimes, onNe
className="w-full mt-3 px-4 py-2 bg-orange-600 hover:bg-orange-700 text-white text-sm rounded-lg transition-colors flex items-center justify-center gap-2"
>
<FaPlus className="w-4 h-4" />
Yeni Mesai Talebi
{translate('::App.Platform.Intranet.Widgets.OvertimeManagement.NewOvertimeRequest')}
</button>
</div>
</div>

View file

@ -1,6 +1,7 @@
import React from 'react'
import { FaChartBar, FaClock, FaUser } from 'react-icons/fa'
import useLocale from '@/utils/hooks/useLocale'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { currentLocalDate } from '@/utils/dateUtils'
import { PriorityEnum, TaskStatusEnum } from '@/types/intranet'
import { ProjectTaskDto } from '@/proxy/intranet/models'
@ -11,6 +12,7 @@ interface PriorityTasksProps {
const PriorityTasks: React.FC<PriorityTasksProps> = ({ tasks }) => {
const currentLocale = useLocale()
const { translate } = useLocalization();
const getPriorityColor = (priority: PriorityEnum) => {
const colors: Record<PriorityEnum, string> = {
@ -28,7 +30,7 @@ const PriorityTasks: React.FC<PriorityTasksProps> = ({ tasks }) => {
<div className="p-4 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">
<FaChartBar className="w-5 h-5" />
Öncelikli Görevler
{translate('::App.Platform.Intranet.Widgets.PriorityTasks.Title')}
</h2>
</div>
<div className="divide-y divide-gray-200 dark:divide-gray-700">
@ -47,10 +49,10 @@ const PriorityTasks: React.FC<PriorityTasksProps> = ({ tasks }) => {
<span
className={`px-2 py-0.5 text-xs rounded ${getPriorityColor(task.priority)}`}
>
{task.priority === PriorityEnum.Urgent && '🔥 Acil'}
{task.priority === PriorityEnum.High && 'Yüksek'}
{task.priority === PriorityEnum.Normal && 'Orta'}
{task.priority === PriorityEnum.Low && 'Düşük'}
{task.priority === PriorityEnum.Urgent && translate('::App.Platform.Intranet.Widgets.PriorityTasks.Urgent')}
{task.priority === PriorityEnum.High && translate('::App.Platform.Intranet.Widgets.PriorityTasks.High')}
{task.priority === PriorityEnum.Normal && translate('::App.Platform.Intranet.Widgets.PriorityTasks.Normal')}
{task.priority === PriorityEnum.Low && translate('::App.Platform.Intranet.Widgets.PriorityTasks.Low')}
</span>
</div>
<p className="text-xs text-gray-600 dark:text-gray-400 mb-2">{task.description}</p>
@ -61,7 +63,7 @@ const PriorityTasks: React.FC<PriorityTasksProps> = ({ tasks }) => {
</span>
<span className="flex items-center gap-1">
<FaUser className="w-3 h-3" />
{task.employee.name || 'Atanmadı'}
{task.employee.name || translate('::App.Platform.Intranet.Widgets.PriorityTasks.Unassigned')}
</span>
</div>
</div>

View file

@ -3,6 +3,7 @@ import { FaFileAlt, FaDownload } from 'react-icons/fa'
import dayjs from 'dayjs'
import { DocumentDto } from '@/proxy/intranet/models'
import { getFileIcon, getFileType } from '@/proxy/intranet/utils'
import { useLocalization } from '@/utils/hooks/useLocalization'
const formatFileSize = (bytes: number): string => {
if (bytes === 0) return '0 B'
@ -13,13 +14,14 @@ const formatFileSize = (bytes: number): string => {
}
const RecentDocuments: React.FC<{ documents: DocumentDto[] }> = ({ documents }) => {
const { translate } = useLocalization();
return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4 border-b border-gray-200 dark:border-gray-700">
<div className="flex items-center justify-between">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white flex items-center gap-2">
<FaFileAlt className="w-5 h-5" />
Son Dokümanlar
{translate('::App.Platform.Intranet.Widgets.RecentDocuments.Title')}
</h2>
</div>
</div>
@ -48,7 +50,7 @@ const RecentDocuments: React.FC<{ documents: DocumentDto[] }> = ({ documents })
{doc.isReadOnly && (
<>
<span></span>
<span className="text-orange-500">🔒 Salt okunur</span>
<span className="text-orange-500">🔒 {translate('::App.Platform.Intranet.Widgets.RecentDocuments.ReadOnly')}</span>
</>
)}
</div>
@ -62,7 +64,7 @@ const RecentDocuments: React.FC<{ documents: DocumentDto[] }> = ({ documents })
link.click()
}}
className="p-2 hover:bg-blue-100 dark:hover:bg-blue-900/30 rounded-lg transition-colors group"
title="İndir"
title={translate('::App.Platform.Intranet.Widgets.RecentDocuments.Download')}
>
<FaDownload className="w-5 h-5 text-gray-600 dark:text-gray-400 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors" />
</button>
@ -71,7 +73,7 @@ const RecentDocuments: React.FC<{ documents: DocumentDto[] }> = ({ documents })
))
) : (
<div className="p-4 text-center text-sm text-gray-500 dark:text-gray-400">
Gösterilecek doküman yok.
{translate('::App.Platform.Intranet.Widgets.RecentDocuments.NoDocuments')}
</div>
)}
</div>

View file

@ -1,24 +1,26 @@
import React from 'react'
import { FaTruck } from 'react-icons/fa'
import { ShuttleRouteDto } from '@/proxy/intranet/models'
import { useLocalization } from '@/utils/hooks/useLocalization'
const ShuttleRoute: React.FC<{ shuttleRoutes: ShuttleRouteDto[] }> = ({ shuttleRoutes }) => {
const morningShuttles = shuttleRoutes.filter((s) => s.type === 'morning')
const eveningShuttles = shuttleRoutes.filter((s) => s.type === 'evening')
const { translate } = useLocalization();
return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4 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">
<FaTruck className="w-5 h-5" />
Servis Saatleri
{translate('::App.Platform.Intranet.Widgets.ShuttleRoute.Title')}
</h2>
</div>
<div className="p-4 space-y-4">
{/* Sabah Servisleri */}
<div>
<h3 className="text-sm font-semibold text-gray-900 dark:text-white mb-3 flex items-center gap-2">
🌅 Sabah Servisleri
🌅 {translate('::App.Platform.Intranet.Widgets.ShuttleRoute.Morning')}
</h3>
<div className="space-y-2">
{morningShuttles.slice(0, 2).map((shuttle) => (
@ -52,7 +54,7 @@ const ShuttleRoute: React.FC<{ shuttleRoutes: ShuttleRouteDto[] }> = ({ shuttleR
: 'bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300'
}`}
>
{shuttle.available} yer
{shuttle.available} {translate('::App.Platform.Intranet.Widgets.ShuttleRoute.Seat')}
</span>
</div>
</div>
@ -63,7 +65,7 @@ const ShuttleRoute: React.FC<{ shuttleRoutes: ShuttleRouteDto[] }> = ({ shuttleR
{/* Akşam Servisleri */}
<div>
<h3 className="text-sm font-semibold text-gray-900 dark:text-white mb-3 flex items-center gap-2">
🌆 Akşam Servisleri
🌆 {translate('::App.Platform.Intranet.Widgets.ShuttleRoute.Evening')}
</h3>
<div className="space-y-2">
{eveningShuttles.slice(0, 2).map((shuttle) => (
@ -97,7 +99,7 @@ const ShuttleRoute: React.FC<{ shuttleRoutes: ShuttleRouteDto[] }> = ({ shuttleR
: 'bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300'
}`}
>
{shuttle.available} yer
{shuttle.available} {translate('::App.Platform.Intranet.Widgets.ShuttleRoute.Seat')}
</span>
</div>
</div>

View file

@ -1,15 +1,17 @@
import React from 'react'
import dayjs from 'dayjs'
import { EmployeeDto } from '@/proxy/intranet/models'
import { useLocalization } from '@/utils/hooks/useLocalization'
const TodayBirthdays: React.FC<{ employees: EmployeeDto[] }> = ({ employees }) => {
const today = dayjs()
const { translate } = useLocalization();
return (
<div className="bg-gradient-to-br from-pink-50 to-purple-50 dark:from-pink-900/20 dark:to-purple-900/20 rounded-lg shadow-sm border border-pink-200 dark:border-pink-800">
<div className="p-4 border-b border-pink-200 dark:border-pink-700">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white flex items-center gap-2">
🎂 Bugün Doğanlar
🎂 {translate('::App.Platform.Intranet.Widgets.TodayBirthdays.Title')}
</h2>
</div>
<div className="p-4 space-y-3">
@ -30,10 +32,10 @@ const TodayBirthdays: React.FC<{ employees: EmployeeDto[] }> = ({ employees }) =
{birthday.name}
</p>
<p className="text-xs text-gray-600 dark:text-gray-400">
{today.diff(dayjs(birthday.birthDate), 'year')} yaşında 🎉
{translate('::App.Platform.Intranet.Widgets.TodayBirthdays.Age', { age: today.diff(dayjs(birthday.birthDate), 'year') })} 🎉
</p>
<p className="text-xs text-gray-500 dark:text-gray-500 mt-1">
{birthday.department?.name || 'Genel'}
{birthday.department?.name || translate('::App.Platform.Intranet.Widgets.TodayBirthdays.General')}
</p>
</div>
</div>
@ -41,7 +43,7 @@ const TodayBirthdays: React.FC<{ employees: EmployeeDto[] }> = ({ employees }) =
</div>
) : (
<p className="text-sm text-gray-500 dark:text-gray-400 text-center py-4">
Bugün doğan yok
{translate('::App.Platform.Intranet.Widgets.TodayBirthdays.NoBirthday')}
</p>
)}
</div>

View file

@ -4,9 +4,11 @@ import dayjs from 'dayjs'
import { EventDto } from '@/proxy/intranet/models'
import useLocale from '@/utils/hooks/useLocale'
import { currentLocalDate } from '@/utils/dateUtils'
import { useLocalization } from '@/utils/hooks/useLocalization'
const UpcomingEvents: React.FC<{ events: EventDto[] }> = ({ events }) => {
const currentLocale = useLocale()
const { translate } = useLocalization();
const upcomingEvents = events.filter(
(event) =>
@ -20,7 +22,7 @@ const UpcomingEvents: React.FC<{ events: EventDto[] }> = ({ events }) => {
<div className="p-4 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">
<FaCalendarAlt className="w-5 h-5" />
Yaklaşan Etkinlikler
{translate('::App.Platform.Intranet.Widgets.UpcomingEvents.Title')}
</h2>
</div>
<div className="p-4 space-y-3">
@ -38,7 +40,7 @@ const UpcomingEvents: React.FC<{ events: EventDto[] }> = ({ events }) => {
))
) : (
<p className="text-sm text-gray-500 dark:text-gray-400 text-center py-4">
Yaklaşan etkinlik yok
{translate('::App.Platform.Intranet.Widgets.UpcomingEvents.NoEvent')}
</p>
)}
</div>

View file

@ -3,16 +3,18 @@ import { FaGraduationCap } from 'react-icons/fa'
import { TrainingDto } from '@/proxy/intranet/models'
import { currentLocalDate } from '@/utils/dateUtils'
import useLocale from '@/utils/hooks/useLocale'
import { useLocalization } from '@/utils/hooks/useLocalization'
const UpcomingTrainings: React.FC<{ trainings: TrainingDto[] }> = ({ trainings }) => {
const currentLocale = useLocale()
const { translate } = useLocalization();
return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4 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">
<FaGraduationCap className="w-5 h-5" />
Yaklaşan Eğitimler
{translate('::App.Platform.Intranet.Widgets.UpcomingTrainings.Title')}
</h2>
</div>
<div className="p-4 space-y-3">
@ -43,7 +45,7 @@ const UpcomingTrainings: React.FC<{ trainings: TrainingDto[] }> = ({ trainings }
))}
{trainings.filter((t) => t.status === 'upcoming').length === 0 && (
<p className="text-sm text-gray-500 dark:text-gray-400 text-center py-4">
Yaklaşan eğitim yok
{translate('::App.Platform.Intranet.Widgets.UpcomingTrainings.NoTraining')}
</p>
)}
</div>

View file

@ -2,15 +2,17 @@ import React from 'react'
import { FaUser, FaUserCheck, FaUserClock } from 'react-icons/fa'
import dayjs from 'dayjs'
import { VisitorDto } from '@/proxy/intranet/models'
import { useLocalization } from '@/utils/hooks/useLocalization'
const Visitors: React.FC<{ visitors: VisitorDto[] }> = ({ visitors }) => {
const { translate } = useLocalization();
const getStatusIcon = (status: string) => {
switch (status) {
case 'Giriş':
case translate('::App.Platform.Intranet.Widgets.Visitors.Status.Entry', 'Giriş'):
return <FaUserCheck className="w-4 h-4 text-green-600" />
case ıkış':
case translate('::App.Platform.Intranet.Widgets.Visitors.Status.Exit', ıkış'):
return <FaUser className="w-4 h-4 text-gray-600" />
case 'Planlandı':
case translate('::App.Platform.Intranet.Widgets.Visitors.Status.Planned', 'Planlandı'):
return <FaUserClock className="w-4 h-4 text-blue-600" />
default:
return <FaUser className="w-4 h-4 text-gray-600" />
@ -19,14 +21,14 @@ const Visitors: React.FC<{ visitors: VisitorDto[] }> = ({ visitors }) => {
const getStatusText = (status: string) => {
switch (status) {
case 'Giriş':
return 'Giriş Yaptı'
case ıkış':
return ıkış Yaptı'
case 'Planlandı':
return 'Planlandı'
case translate('::App.Platform.Intranet.Widgets.Visitors.Status.Entry', 'Giriş'):
return translate('::App.Platform.Intranet.Widgets.Visitors.StatusText.Entry')
case translate('::App.Platform.Intranet.Widgets.Visitors.Status.Exit', ıkış'):
return translate('::App.Platform.Intranet.Widgets.Visitors.StatusText.Exit')
case translate('::App.Platform.Intranet.Widgets.Visitors.Status.Planned', 'Planlandı'):
return translate('::App.Platform.Intranet.Widgets.Visitors.StatusText.Planned')
default:
return 'Bilinmiyor'
return translate('::App.Platform.Intranet.Widgets.Visitors.StatusText.Unknown')
}
}
@ -48,7 +50,7 @@ const Visitors: React.FC<{ visitors: VisitorDto[] }> = ({ visitors }) => {
<div className="p-4 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
{translate('::App.Platform.Intranet.Widgets.Visitors.Title')}
</h2>
</div>
<div className="p-4 space-y-3">
@ -90,7 +92,7 @@ const Visitors: React.FC<{ visitors: VisitorDto[] }> = ({ visitors }) => {
</div>
{visitor.employee && (
<p className="text-xs text-gray-500 dark:text-gray-500 mt-1">
Karşılayan: {visitor.employee.name}
{translate('::App.Platform.Intranet.Widgets.Visitors.Host')}: {visitor.employee.name}
</p>
)}
</div>
@ -99,7 +101,7 @@ const Visitors: React.FC<{ visitors: VisitorDto[] }> = ({ visitors }) => {
))
) : (
<p className="text-sm text-gray-500 dark:text-gray-400 text-center py-4">
Bugün ziyaretçi yok
{translate('::App.Platform.Intranet.Widgets.Visitors.NoVisitor')}
</p>
)}
</div>