erp-platform/ui/src/views/hr/components/Degree360Templates.tsx

780 lines
30 KiB
TypeScript
Raw Normal View History

2025-09-15 19:46:52 +00:00
import React, { useState } from 'react'
import { FaEye, FaEdit, FaPlus, FaTimes, FaSave, FaTrash, FaQuestionCircle } from 'react-icons/fa'
2025-09-15 09:31:47 +00:00
import {
HrEvaluation360Template,
HrQuestionGroup,
HrEvaluationQuestion,
QuestionTypeEnum,
HrQuestionOption,
AssessorTypeEnum,
2025-09-15 19:46:52 +00:00
} from '../../../types/hr'
import DataTable, { Column } from '../../../components/common/DataTable'
import { mockEvaluation360Templates } from '../../../mocks/mockEvaluation360Templates'
import Widget from '../../../components/common/Widget'
import { Container } from '@/components/shared'
2025-09-15 09:31:47 +00:00
const Degree360Templates: React.FC = () => {
2025-09-15 19:46:52 +00:00
const [templateSearchTerm, setTemplateSearchTerm] = useState('')
2025-09-15 09:31:47 +00:00
// Modal states
2025-09-15 19:46:52 +00:00
const [showTemplateModal, setShowTemplateModal] = useState(false)
const [showQuestionModal, setShowQuestionModal] = useState(false)
const [showQuestionItemModal, setShowQuestionItemModal] = useState(false)
const [selectedTemplate, setSelectedTemplate] = useState<HrEvaluation360Template | null>(null)
const [selectedQuestionGroup, setSelectedQuestionGroup] = useState<HrQuestionGroup | null>(null)
const [selectedQuestion, setSelectedQuestion] = useState<HrEvaluationQuestion | null>(null)
const [isEditMode, setIsEditMode] = useState(false)
2025-09-15 09:31:47 +00:00
// Form states
const [templateForm, setTemplateForm] = useState({
2025-09-15 19:46:52 +00:00
name: '',
description: '',
2025-09-15 09:31:47 +00:00
isActive: true,
assessorTypes: [] as AssessorTypeEnum[],
2025-09-15 19:46:52 +00:00
})
2025-09-15 09:31:47 +00:00
const [questionGroupForm, setQuestionGroupForm] = useState({
2025-09-15 19:46:52 +00:00
groupName: '',
description: '',
2025-09-15 09:31:47 +00:00
weight: 0,
order: 0,
2025-09-15 19:46:52 +00:00
})
2025-09-15 09:31:47 +00:00
const [questionForm, setQuestionForm] = useState({
2025-09-15 19:46:52 +00:00
questionText: '',
2025-09-15 09:31:47 +00:00
questionType: QuestionTypeEnum.Rating,
isRequired: true,
order: 0,
weight: 0,
options: [] as HrQuestionOption[],
2025-09-15 19:46:52 +00:00
})
2025-09-15 09:31:47 +00:00
// Filter templates
const filteredTemplates = mockEvaluation360Templates.filter((template) => {
2025-09-15 19:46:52 +00:00
const searchLower = templateSearchTerm.toLowerCase()
2025-09-15 09:31:47 +00:00
return (
template.name.toLowerCase().includes(searchLower) ||
template.description.toLowerCase().includes(searchLower)
2025-09-15 19:46:52 +00:00
)
})
2025-09-15 09:31:47 +00:00
// Statistics
2025-09-15 19:46:52 +00:00
const totalTemplates = mockEvaluation360Templates.length
const activeTemplates = mockEvaluation360Templates.filter((t) => t.isActive).length
2025-09-15 09:31:47 +00:00
// Event handlers
const handleNewTemplate = () => {
setTemplateForm({
2025-09-15 19:46:52 +00:00
name: '',
description: '',
2025-09-15 09:31:47 +00:00
isActive: true,
assessorTypes: [],
2025-09-15 19:46:52 +00:00
})
setSelectedTemplate(null)
setIsEditMode(false)
setShowTemplateModal(true)
}
2025-09-15 09:31:47 +00:00
const handleEditTemplate = (template: HrEvaluation360Template) => {
setTemplateForm({
name: template.name,
description: template.description,
isActive: template.isActive,
assessorTypes: template.assessorTypes || [],
2025-09-15 19:46:52 +00:00
})
setSelectedTemplate(template)
setIsEditMode(true)
setShowTemplateModal(true)
}
2025-09-15 09:31:47 +00:00
const handleViewTemplate = (template: HrEvaluation360Template) => {
setTemplateForm({
name: template.name,
description: template.description,
isActive: template.isActive,
assessorTypes: template.assessorTypes || [],
2025-09-15 19:46:52 +00:00
})
setSelectedTemplate(template)
setShowTemplateModal(true)
setIsEditMode(false)
}
2025-09-15 09:31:47 +00:00
const handleSaveTemplate = () => {
2025-09-15 19:46:52 +00:00
console.log('Saving template:', templateForm)
setShowTemplateModal(false)
}
2025-09-15 09:31:47 +00:00
const handleDeleteTemplate = (template: HrEvaluation360Template) => {
2025-09-15 19:46:52 +00:00
if (confirm(`"${template.name}" şablonunu silmek istediğinizden emin misiniz?`)) {
console.log('Deleting template:', template.id)
2025-09-15 09:31:47 +00:00
}
2025-09-15 19:46:52 +00:00
}
2025-09-15 09:31:47 +00:00
const handleAddQuestionGroup = () => {
setQuestionGroupForm({
2025-09-15 19:46:52 +00:00
groupName: '',
description: '',
2025-09-15 09:31:47 +00:00
weight: 0,
order: 0,
2025-09-15 19:46:52 +00:00
})
setSelectedQuestionGroup(null)
setShowQuestionModal(true)
}
2025-09-15 09:31:47 +00:00
const handleEditQuestionGroup = (group: HrQuestionGroup) => {
setQuestionGroupForm({
groupName: group.groupName,
2025-09-15 19:46:52 +00:00
description: group.description || '',
2025-09-15 09:31:47 +00:00
weight: group.weight,
order: group.order,
2025-09-15 19:46:52 +00:00
})
setSelectedQuestionGroup(group)
setShowQuestionModal(true)
}
2025-09-15 09:31:47 +00:00
const handleSaveQuestionGroup = () => {
2025-09-15 19:46:52 +00:00
console.log('Saving question group:', questionGroupForm)
setShowQuestionModal(false)
}
2025-09-15 09:31:47 +00:00
const handleAddQuestion = (group: HrQuestionGroup) => {
setQuestionForm({
2025-09-15 19:46:52 +00:00
questionText: '',
2025-09-15 09:31:47 +00:00
questionType: QuestionTypeEnum.Rating,
isRequired: true,
order: 0,
weight: 0,
options: [],
2025-09-15 19:46:52 +00:00
})
setSelectedQuestion(null)
setSelectedQuestionGroup(group)
setShowQuestionItemModal(true)
}
const handleEditQuestion = (question: HrEvaluationQuestion, group: HrQuestionGroup) => {
2025-09-15 09:31:47 +00:00
setQuestionForm({
questionText: question.questionText,
questionType: question.questionType,
isRequired: question.isRequired,
order: question.order,
weight: question.weight,
options: question.options || [],
2025-09-15 19:46:52 +00:00
})
setSelectedQuestion(question)
setSelectedQuestionGroup(group)
setShowQuestionItemModal(true)
}
2025-09-15 09:31:47 +00:00
const handleSaveQuestion = () => {
2025-09-15 19:46:52 +00:00
console.log('Saving question:', questionForm)
setShowQuestionItemModal(false)
}
2025-09-15 09:31:47 +00:00
// Table columns
const templateColumns: Column<HrEvaluation360Template>[] = [
{
2025-09-15 19:46:52 +00:00
key: 'name',
header: 'Şablon Adı',
2025-09-15 09:31:47 +00:00
sortable: true,
render: (template) => (
<div>
<div className="font-medium text-gray-900">{template.name}</div>
<div className="text-sm text-gray-500">{template.description}</div>
</div>
),
},
{
2025-09-15 19:46:52 +00:00
key: 'questionGroups',
header: 'Soru Grupları',
2025-09-15 09:31:47 +00:00
render: (template) => (
2025-09-15 19:46:52 +00:00
<span className="text-sm text-gray-600">{template.questionGroups?.length || 0} grup</span>
2025-09-15 09:31:47 +00:00
),
},
{
2025-09-15 19:46:52 +00:00
key: 'assessorTypes',
header: 'Değerlendirecekler',
2025-09-15 09:31:47 +00:00
render: (template) => {
const assessorLabels = {
2025-09-15 19:46:52 +00:00
[AssessorTypeEnum.Self]: 'Kendi',
[AssessorTypeEnum.Manager]: 'Yönetici',
[AssessorTypeEnum.Peer]: 'Meslektaş',
[AssessorTypeEnum.Subordinate]: 'Ast',
[AssessorTypeEnum.Customer]: 'Müşteri',
[AssessorTypeEnum.OtherDepartment]: 'Diğer Departman',
[AssessorTypeEnum.HRUpperManagement]: 'İK/Üst Yönetim',
[AssessorTypeEnum.External]: 'Dış Paydaş',
}
const assessorTypes = template.assessorTypes || []
2025-09-15 09:31:47 +00:00
return (
<div className="flex flex-wrap gap-1">
{assessorTypes.map((type) => (
<span
key={type}
className="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800"
>
{assessorLabels[type] || type}
</span>
))}
{assessorTypes.length === 0 && (
<span className="text-sm text-gray-400">Belirtilmemiş</span>
)}
</div>
2025-09-15 19:46:52 +00:00
)
2025-09-15 09:31:47 +00:00
},
},
{
2025-09-15 19:46:52 +00:00
key: 'isActive',
header: 'Durum',
2025-09-15 09:31:47 +00:00
render: (template) => (
<span
className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
2025-09-15 19:46:52 +00:00
template.isActive ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'
2025-09-15 09:31:47 +00:00
}`}
>
2025-09-15 19:46:52 +00:00
{template.isActive ? 'Aktif' : 'Pasif'}
2025-09-15 09:31:47 +00:00
</span>
),
},
{
2025-09-15 19:46:52 +00:00
key: 'actions',
header: 'İşlemler',
2025-09-15 09:31:47 +00:00
render: (template) => (
<div className="flex items-center gap-2">
<button
onClick={() => handleViewTemplate(template)}
className="text-blue-600 hover:text-blue-900"
title="Görüntüle"
>
<FaEye className="w-4 h-4" />
</button>
<button
onClick={() => handleEditTemplate(template)}
className="text-green-600 hover:text-green-900"
title="Düzenle"
>
<FaEdit className="w-4 h-4" />
</button>
<button
onClick={() => handleDeleteTemplate(template)}
className="text-red-600 hover:text-red-900"
title="Sil"
>
<FaTrash className="w-4 h-4" />
</button>
</div>
),
},
2025-09-15 19:46:52 +00:00
]
2025-09-15 09:31:47 +00:00
return (
2025-09-15 19:46:52 +00:00
<Container>
<div className="space-y-2">
{/* Header */}
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<div>
<h2 className="text-xl font-bold text-gray-900">360° Şablonlar</h2>
<p className="text-gray-600 mt-1">360 derece değerlendirme şablonlarını yönetin</p>
</div>
<button
onClick={handleNewTemplate}
className="flex items-center gap-2 px-3 py-1.5 bg-purple-600 text-white rounded-md hover:bg-purple-700 ml-4 text-sm"
>
<FaPlus className="w-4 h-4" />
Yeni Şablon
</button>
2025-09-15 09:31:47 +00:00
</div>
2025-09-15 19:46:52 +00:00
{/* Statistics */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Widget
title="Toplam Şablon"
value={totalTemplates}
color="purple"
icon="FaClipboardList"
/>
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
<Widget
title="Aktif Şablon"
value={activeTemplates}
color="green"
icon="FaClipboardList"
/>
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
<Widget
title="Pasif Şablon"
value={totalTemplates - activeTemplates}
color="red"
icon="FaClipboardList"
2025-09-15 09:31:47 +00:00
/>
</div>
2025-09-15 19:46:52 +00:00
<div className="bg-white p-4 rounded-lg border">
<div className="flex-1">
<input
type="text"
placeholder="Şablon adı veya açıklama ile ara..."
value={templateSearchTerm}
onChange={(e) => setTemplateSearchTerm(e.target.value)}
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
/>
</div>
</div>
{/* Templates Table */}
<DataTable data={filteredTemplates} columns={templateColumns} />
</div>
2025-09-15 09:31:47 +00:00
{/* Template Modal */}
{showTemplateModal && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto">
<div className="flex justify-between items-center mb-4">
<h2 className="text-lg font-bold">
2025-09-15 19:46:52 +00:00
{isEditMode ? 'Şablon Düzenle' : selectedTemplate ? 'Şablon Detayı' : 'Yeni Şablon'}
2025-09-15 09:31:47 +00:00
</h2>
<button
onClick={() => setShowTemplateModal(false)}
className="p-2 text-gray-500 hover:text-gray-700"
>
<FaTimes className="w-5 h-5" />
</button>
</div>
<div className="space-y-4">
{/* Basic Information */}
<div className="grid grid-cols-2 gap-4">
<div>
2025-09-15 19:46:52 +00:00
<label className="block text-sm font-medium text-gray-700 mb-2">Şablon Adı</label>
2025-09-15 09:31:47 +00:00
<input
type="text"
value={templateForm.name}
2025-09-15 19:46:52 +00:00
onChange={(e) => setTemplateForm({ ...templateForm, name: e.target.value })}
2025-09-15 09:31:47 +00:00
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
disabled={!isEditMode && !!selectedTemplate}
/>
</div>
<div>
2025-09-15 19:46:52 +00:00
<label className="block text-sm font-medium text-gray-700 mb-2">Durum</label>
2025-09-15 09:31:47 +00:00
<select
2025-09-15 19:46:52 +00:00
value={templateForm.isActive ? 'active' : 'inactive'}
2025-09-15 09:31:47 +00:00
onChange={(e) =>
setTemplateForm({
...templateForm,
2025-09-15 19:46:52 +00:00
isActive: e.target.value === 'active',
2025-09-15 09:31:47 +00:00
})
}
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
disabled={!isEditMode && !!selectedTemplate}
>
<option value="active">Aktif</option>
<option value="inactive">Pasif</option>
</select>
</div>
</div>
<div>
2025-09-15 19:46:52 +00:00
<label className="block text-sm font-medium text-gray-700 mb-2">ıklama</label>
2025-09-15 09:31:47 +00:00
<textarea
value={templateForm.description}
onChange={(e) =>
setTemplateForm({
...templateForm,
description: e.target.value,
})
}
rows={3}
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
disabled={!isEditMode && !!selectedTemplate}
/>
</div>
{/* Değerlendiriciler */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Değerlendirecekler
</label>
<div className="grid grid-cols-2 gap-3">
{Object.values(AssessorTypeEnum).map((type) => {
const labels = {
2025-09-15 19:46:52 +00:00
[AssessorTypeEnum.Self]: 'Kendi',
[AssessorTypeEnum.Manager]: 'Yönetici',
[AssessorTypeEnum.Peer]: 'Meslektaş',
[AssessorTypeEnum.Subordinate]: 'Ast',
[AssessorTypeEnum.Customer]: 'Müşteri',
[AssessorTypeEnum.OtherDepartment]: 'Diğer Departman',
[AssessorTypeEnum.HRUpperManagement]: 'İK/Üst Yönetim',
[AssessorTypeEnum.External]: 'Dış Paydaş',
}
2025-09-15 09:31:47 +00:00
return (
<label key={type} className="flex items-center space-x-2">
<input
type="checkbox"
checked={templateForm.assessorTypes.includes(type)}
onChange={(e) => {
if (e.target.checked) {
setTemplateForm({
...templateForm,
2025-09-15 19:46:52 +00:00
assessorTypes: [...templateForm.assessorTypes, type],
})
2025-09-15 09:31:47 +00:00
} else {
setTemplateForm({
...templateForm,
2025-09-15 19:46:52 +00:00
assessorTypes: templateForm.assessorTypes.filter((t) => t !== type),
})
2025-09-15 09:31:47 +00:00
}
}}
className="rounded border-gray-300 text-purple-600 focus:ring-purple-500"
disabled={!isEditMode && !!selectedTemplate}
/>
2025-09-15 19:46:52 +00:00
<span className="text-sm text-gray-700">{labels[type] || type}</span>
2025-09-15 09:31:47 +00:00
</label>
2025-09-15 19:46:52 +00:00
)
2025-09-15 09:31:47 +00:00
})}
</div>
</div>
{/* Question Groups */}
{selectedTemplate && (
<div>
<div className="flex justify-between items-center mb-4">
<h3 className="text-lg font-semibold">Soru Grupları</h3>
{isEditMode && (
<button
onClick={handleAddQuestionGroup}
className="flex items-center gap-2 px-2 py-1 bg-blue-600 text-white rounded-md hover:bg-blue-700 text-xs"
>
<FaPlus className="w-3 h-3" />
Grup Ekle
</button>
)}
</div>
<div className="space-y-3">
2025-09-15 19:46:52 +00:00
{selectedTemplate.questionGroups?.map((group, groupIndex) => (
<div key={groupIndex} className="bg-gray-50 p-3 rounded-lg">
<div className="flex justify-between items-start mb-3">
<div>
<h4 className="font-medium">{group.groupName}</h4>
<p className="text-sm text-gray-600">{group.description}</p>
<p className="text-sm text-gray-600">ırlık: {group.weight}%</p>
2025-09-15 09:31:47 +00:00
</div>
2025-09-15 19:46:52 +00:00
{isEditMode && (
<div className="flex gap-2">
<button
onClick={() => handleEditQuestionGroup(group)}
className="text-blue-600 hover:text-blue-900"
>
<FaEdit className="w-4 h-4" />
</button>
<button
onClick={() => handleAddQuestion(group)}
className="text-green-600 hover:text-green-900"
2025-09-15 09:31:47 +00:00
>
2025-09-15 19:46:52 +00:00
<FaQuestionCircle className="w-4 h-4" />
</button>
</div>
)}
</div>
{/* Questions */}
<div className="space-y-2">
{group.questions?.map((question, questionIndex) => (
<div key={questionIndex} className="bg-white p-2 rounded border">
<div className="flex justify-between items-start">
<div className="flex-1">
<p className="text-sm">{question.questionText}</p>
<div className="flex gap-4 mt-1">
<span className="text-xs text-gray-500">
Tip:{' '}
{question.questionType === QuestionTypeEnum.Rating
? 'Puanlama'
: question.questionType === QuestionTypeEnum.MultipleChoice
? 'Çoktan Seçmeli'
: question.questionType === QuestionTypeEnum.Text
? 'Metin'
: 'Evet/Hayır'}
</span>
<span className="text-xs text-gray-500">
ırlık: {question.weight}%
</span>
{question.isRequired && (
<span className="text-xs text-red-500">Zorunlu</span>
)}
2025-09-15 09:31:47 +00:00
</div>
</div>
2025-09-15 19:46:52 +00:00
{isEditMode && (
<button
onClick={() => handleEditQuestion(question, group)}
className="text-blue-600 hover:text-blue-900"
>
<FaEdit className="w-4 h-4" />
</button>
)}
2025-09-15 09:31:47 +00:00
</div>
2025-09-15 19:46:52 +00:00
</div>
))}
2025-09-15 09:31:47 +00:00
</div>
2025-09-15 19:46:52 +00:00
</div>
))}
2025-09-15 09:31:47 +00:00
</div>
</div>
)}
</div>
<div className="flex justify-end gap-4 mt-4">
<button
onClick={() => setShowTemplateModal(false)}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50"
>
2025-09-15 19:46:52 +00:00
{selectedTemplate && !isEditMode ? 'Kapat' : 'İptal'}
2025-09-15 09:31:47 +00:00
</button>
{(isEditMode || !selectedTemplate) && (
<button
onClick={handleSaveTemplate}
className="flex items-center gap-2 px-3 py-1.5 text-sm bg-purple-600 text-white rounded-md hover:bg-purple-700"
>
<FaSave className="w-4 h-4" />
Kaydet
</button>
)}
</div>
</div>
</div>
)}
{/* Question Group Modal */}
{showQuestionModal && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg p-6 w-full max-w-md">
<div className="flex justify-between items-center mb-4">
<h2 className="text-lg font-bold">
2025-09-15 19:46:52 +00:00
{selectedQuestionGroup ? 'Soru Grubu Düzenle' : 'Yeni Soru Grubu'}
2025-09-15 09:31:47 +00:00
</h2>
<button
onClick={() => setShowQuestionModal(false)}
className="p-2 text-gray-500 hover:text-gray-700"
>
<FaTimes className="w-5 h-5" />
</button>
</div>
<div className="space-y-4">
<div>
2025-09-15 19:46:52 +00:00
<label className="block text-sm font-medium text-gray-700 mb-2">Grup Adı</label>
2025-09-15 09:31:47 +00:00
<input
type="text"
value={questionGroupForm.groupName}
onChange={(e) =>
setQuestionGroupForm({
...questionGroupForm,
groupName: e.target.value,
})
}
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
/>
</div>
<div>
2025-09-15 19:46:52 +00:00
<label className="block text-sm font-medium text-gray-700 mb-2">ıklama</label>
2025-09-15 09:31:47 +00:00
<textarea
value={questionGroupForm.description}
onChange={(e) =>
setQuestionGroupForm({
...questionGroupForm,
description: e.target.value,
})
}
rows={3}
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
ırlık (%)
</label>
<input
type="number"
min="0"
max="100"
value={questionGroupForm.weight}
onChange={(e) =>
setQuestionGroupForm({
...questionGroupForm,
weight: Number(e.target.value),
})
}
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
/>
</div>
<div>
2025-09-15 19:46:52 +00:00
<label className="block text-sm font-medium text-gray-700 mb-2">Sıra</label>
2025-09-15 09:31:47 +00:00
<input
type="number"
min="0"
value={questionGroupForm.order}
onChange={(e) =>
setQuestionGroupForm({
...questionGroupForm,
order: Number(e.target.value),
})
}
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
/>
</div>
</div>
</div>
<div className="flex justify-end gap-4 mt-4">
<button
onClick={() => setShowQuestionModal(false)}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50"
>
İptal
</button>
<button
onClick={handleSaveQuestionGroup}
className="flex items-center gap-2 px-3 py-1.5 text-sm bg-purple-600 text-white rounded-md hover:bg-purple-700"
>
<FaSave className="w-4 h-4" />
Kaydet
</button>
</div>
</div>
</div>
)}
{/* Question Modal */}
{showQuestionItemModal && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg p-6 w-full max-w-md">
<div className="flex justify-between items-center mb-4">
<h2 className="text-lg font-bold">
2025-09-15 19:46:52 +00:00
{selectedQuestion ? 'Soru Düzenle' : 'Yeni Soru'}
2025-09-15 09:31:47 +00:00
</h2>
<button
onClick={() => setShowQuestionItemModal(false)}
className="p-2 text-gray-500 hover:text-gray-700"
>
<FaTimes className="w-5 h-5" />
</button>
</div>
<div className="space-y-4">
<div>
2025-09-15 19:46:52 +00:00
<label className="block text-sm font-medium text-gray-700 mb-2">Soru Metni</label>
2025-09-15 09:31:47 +00:00
<textarea
value={questionForm.questionText}
onChange={(e) =>
setQuestionForm({
...questionForm,
questionText: e.target.value,
})
}
rows={3}
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
/>
</div>
<div>
2025-09-15 19:46:52 +00:00
<label className="block text-sm font-medium text-gray-700 mb-2">Soru Tipi</label>
2025-09-15 09:31:47 +00:00
<select
value={questionForm.questionType}
onChange={(e) =>
setQuestionForm({
...questionForm,
questionType: e.target.value as QuestionTypeEnum,
})
}
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
>
<option value={QuestionTypeEnum.Rating}>Puanlama</option>
2025-09-15 19:46:52 +00:00
<option value={QuestionTypeEnum.MultipleChoice}>Çoktan Seçmeli</option>
2025-09-15 09:31:47 +00:00
<option value={QuestionTypeEnum.Text}>Metin</option>
<option value={QuestionTypeEnum.YesNo}>Evet/Hayır</option>
</select>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
ırlık (%)
</label>
<input
type="number"
min="0"
max="100"
value={questionForm.weight}
onChange={(e) =>
setQuestionForm({
...questionForm,
weight: Number(e.target.value),
})
}
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
/>
</div>
<div>
2025-09-15 19:46:52 +00:00
<label className="block text-sm font-medium text-gray-700 mb-2">Sıra</label>
2025-09-15 09:31:47 +00:00
<input
type="number"
min="0"
value={questionForm.order}
onChange={(e) =>
setQuestionForm({
...questionForm,
order: Number(e.target.value),
})
}
className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
/>
</div>
</div>
<div className="flex items-center">
<input
type="checkbox"
id="isRequired"
checked={questionForm.isRequired}
onChange={(e) =>
setQuestionForm({
...questionForm,
isRequired: e.target.checked,
})
}
className="h-4 w-4 text-purple-600 focus:ring-purple-500 border-gray-300 rounded"
/>
2025-09-15 19:46:52 +00:00
<label htmlFor="isRequired" className="ml-2 block text-sm text-gray-700">
2025-09-15 09:31:47 +00:00
Zorunlu soru
</label>
</div>
</div>
<div className="flex justify-end gap-4 mt-4">
<button
onClick={() => setShowQuestionItemModal(false)}
className="px-3 py-1.5 text-sm border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50"
>
İptal
</button>
<button
onClick={handleSaveQuestion}
className="flex items-center gap-2 px-3 py-1.5 text-sm bg-purple-600 text-white rounded-md hover:bg-purple-700"
>
<FaSave className="w-4 h-4" />
Kaydet
</button>
</div>
</div>
</div>
)}
2025-09-15 19:46:52 +00:00
</Container>
)
}
2025-09-15 09:31:47 +00:00
2025-09-15 19:46:52 +00:00
export default Degree360Templates