781 lines
30 KiB
TypeScript
781 lines
30 KiB
TypeScript
import React, { useState } from 'react'
|
||
import { FaEye, FaEdit, FaPlus, FaTimes, FaSave, FaTrash, FaQuestionCircle } from 'react-icons/fa'
|
||
import {
|
||
HrEvaluation360Template,
|
||
HrQuestionGroup,
|
||
HrEvaluationQuestion,
|
||
QuestionTypeEnum,
|
||
HrQuestionOption,
|
||
AssessorTypeEnum,
|
||
getQuestionTypeText,
|
||
} 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'
|
||
|
||
const Degree360Templates: React.FC = () => {
|
||
const [templateSearchTerm, setTemplateSearchTerm] = useState('')
|
||
|
||
// Modal states
|
||
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)
|
||
|
||
// Form states
|
||
const [templateForm, setTemplateForm] = useState({
|
||
name: '',
|
||
description: '',
|
||
isActive: true,
|
||
assessorTypes: [] as AssessorTypeEnum[],
|
||
})
|
||
|
||
const [questionGroupForm, setQuestionGroupForm] = useState({
|
||
groupName: '',
|
||
description: '',
|
||
weight: 0,
|
||
order: 0,
|
||
})
|
||
|
||
const [questionForm, setQuestionForm] = useState({
|
||
questionText: '',
|
||
questionType: QuestionTypeEnum.Rating,
|
||
isRequired: true,
|
||
order: 0,
|
||
weight: 0,
|
||
options: [] as HrQuestionOption[],
|
||
})
|
||
|
||
// Filter templates
|
||
const filteredTemplates = mockEvaluation360Templates.filter((template) => {
|
||
const searchLower = templateSearchTerm.toLowerCase()
|
||
return (
|
||
template.name.toLowerCase().includes(searchLower) ||
|
||
template.description.toLowerCase().includes(searchLower)
|
||
)
|
||
})
|
||
|
||
// Statistics
|
||
const totalTemplates = mockEvaluation360Templates.length
|
||
const activeTemplates = mockEvaluation360Templates.filter((t) => t.isActive).length
|
||
|
||
// Event handlers
|
||
const handleNewTemplate = () => {
|
||
setTemplateForm({
|
||
name: '',
|
||
description: '',
|
||
isActive: true,
|
||
assessorTypes: [],
|
||
})
|
||
setSelectedTemplate(null)
|
||
setIsEditMode(false)
|
||
setShowTemplateModal(true)
|
||
}
|
||
|
||
const handleEditTemplate = (template: HrEvaluation360Template) => {
|
||
setTemplateForm({
|
||
name: template.name,
|
||
description: template.description,
|
||
isActive: template.isActive,
|
||
assessorTypes: template.assessorTypes || [],
|
||
})
|
||
setSelectedTemplate(template)
|
||
setIsEditMode(true)
|
||
setShowTemplateModal(true)
|
||
}
|
||
|
||
const handleViewTemplate = (template: HrEvaluation360Template) => {
|
||
setTemplateForm({
|
||
name: template.name,
|
||
description: template.description,
|
||
isActive: template.isActive,
|
||
assessorTypes: template.assessorTypes || [],
|
||
})
|
||
setSelectedTemplate(template)
|
||
setShowTemplateModal(true)
|
||
setIsEditMode(false)
|
||
}
|
||
|
||
const handleSaveTemplate = () => {
|
||
console.log('Saving template:', templateForm)
|
||
setShowTemplateModal(false)
|
||
}
|
||
|
||
const handleDeleteTemplate = (template: HrEvaluation360Template) => {
|
||
if (confirm(`"${template.name}" şablonunu silmek istediğinizden emin misiniz?`)) {
|
||
console.log('Deleting template:', template.id)
|
||
}
|
||
}
|
||
|
||
const handleAddQuestionGroup = () => {
|
||
setQuestionGroupForm({
|
||
groupName: '',
|
||
description: '',
|
||
weight: 0,
|
||
order: 0,
|
||
})
|
||
setSelectedQuestionGroup(null)
|
||
setShowQuestionModal(true)
|
||
}
|
||
|
||
const handleEditQuestionGroup = (group: HrQuestionGroup) => {
|
||
setQuestionGroupForm({
|
||
groupName: group.groupName,
|
||
description: group.description || '',
|
||
weight: group.weight,
|
||
order: group.order,
|
||
})
|
||
setSelectedQuestionGroup(group)
|
||
setShowQuestionModal(true)
|
||
}
|
||
|
||
const handleSaveQuestionGroup = () => {
|
||
console.log('Saving question group:', questionGroupForm)
|
||
setShowQuestionModal(false)
|
||
}
|
||
|
||
const handleAddQuestion = (group: HrQuestionGroup) => {
|
||
setQuestionForm({
|
||
questionText: '',
|
||
questionType: QuestionTypeEnum.Rating,
|
||
isRequired: true,
|
||
order: 0,
|
||
weight: 0,
|
||
options: [],
|
||
})
|
||
setSelectedQuestion(null)
|
||
setSelectedQuestionGroup(group)
|
||
setShowQuestionItemModal(true)
|
||
}
|
||
|
||
const handleEditQuestion = (question: HrEvaluationQuestion, group: HrQuestionGroup) => {
|
||
setQuestionForm({
|
||
questionText: question.questionText,
|
||
questionType: question.questionType,
|
||
isRequired: question.isRequired,
|
||
order: question.order,
|
||
weight: question.weight,
|
||
options: question.options || [],
|
||
})
|
||
setSelectedQuestion(question)
|
||
setSelectedQuestionGroup(group)
|
||
setShowQuestionItemModal(true)
|
||
}
|
||
|
||
const handleSaveQuestion = () => {
|
||
console.log('Saving question:', questionForm)
|
||
setShowQuestionItemModal(false)
|
||
}
|
||
|
||
// Table columns
|
||
const templateColumns: Column<HrEvaluation360Template>[] = [
|
||
{
|
||
key: 'name',
|
||
header: 'Şablon Adı',
|
||
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>
|
||
),
|
||
},
|
||
{
|
||
key: 'questionGroups',
|
||
header: 'Soru Grupları',
|
||
render: (template) => (
|
||
<span className="text-sm text-gray-600">{template.questionGroups?.length || 0} grup</span>
|
||
),
|
||
},
|
||
{
|
||
key: 'assessorTypes',
|
||
header: 'Değerlendirecekler',
|
||
render: (template) => {
|
||
const assessorLabels = {
|
||
[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 || []
|
||
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>
|
||
)
|
||
},
|
||
},
|
||
{
|
||
key: 'isActive',
|
||
header: 'Durum',
|
||
render: (template) => (
|
||
<span
|
||
className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
|
||
template.isActive ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'
|
||
}`}
|
||
>
|
||
{template.isActive ? 'Aktif' : 'Pasif'}
|
||
</span>
|
||
),
|
||
},
|
||
{
|
||
key: 'actions',
|
||
header: 'İşlemler',
|
||
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>
|
||
),
|
||
},
|
||
]
|
||
|
||
return (
|
||
<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-2xl font-bold text-gray-900">360° Şablonlar</h2>
|
||
<p className="text-gray-600">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>
|
||
</div>
|
||
|
||
{/* Statistics */}
|
||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||
<Widget
|
||
title="Toplam Şablon"
|
||
value={totalTemplates}
|
||
color="purple"
|
||
icon="FaClipboardList"
|
||
/>
|
||
|
||
<Widget
|
||
title="Aktif Şablon"
|
||
value={activeTemplates}
|
||
color="green"
|
||
icon="FaClipboardList"
|
||
/>
|
||
|
||
<Widget
|
||
title="Pasif Şablon"
|
||
value={totalTemplates - activeTemplates}
|
||
color="red"
|
||
icon="FaClipboardList"
|
||
/>
|
||
</div>
|
||
|
||
<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>
|
||
|
||
{/* 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">
|
||
{isEditMode ? 'Şablon Düzenle' : selectedTemplate ? 'Şablon Detayı' : 'Yeni Şablon'}
|
||
</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>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">Şablon Adı</label>
|
||
<input
|
||
type="text"
|
||
value={templateForm.name}
|
||
onChange={(e) => setTemplateForm({ ...templateForm, name: 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"
|
||
disabled={!isEditMode && !!selectedTemplate}
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">Durum</label>
|
||
<select
|
||
value={templateForm.isActive ? 'active' : 'inactive'}
|
||
onChange={(e) =>
|
||
setTemplateForm({
|
||
...templateForm,
|
||
isActive: e.target.value === 'active',
|
||
})
|
||
}
|
||
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>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">Açıklama</label>
|
||
<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 = {
|
||
[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ş',
|
||
}
|
||
|
||
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,
|
||
assessorTypes: [...templateForm.assessorTypes, type],
|
||
})
|
||
} else {
|
||
setTemplateForm({
|
||
...templateForm,
|
||
assessorTypes: templateForm.assessorTypes.filter((t) => t !== type),
|
||
})
|
||
}
|
||
}}
|
||
className="rounded border-gray-300 text-purple-600 focus:ring-purple-500"
|
||
disabled={!isEditMode && !!selectedTemplate}
|
||
/>
|
||
<span className="text-sm text-gray-700">{labels[type] || type}</span>
|
||
</label>
|
||
)
|
||
})}
|
||
</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">
|
||
{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-gray-600">Ağırlık: {group.weight}%</p>
|
||
</div>
|
||
{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"
|
||
>
|
||
<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">
|
||
Ağırlık: {question.weight}%
|
||
</span>
|
||
{question.isRequired && (
|
||
<span className="text-xs text-red-500">Zorunlu</span>
|
||
)}
|
||
</div>
|
||
</div>
|
||
{isEditMode && (
|
||
<button
|
||
onClick={() => handleEditQuestion(question, group)}
|
||
className="text-blue-600 hover:text-blue-900"
|
||
>
|
||
<FaEdit className="w-4 h-4" />
|
||
</button>
|
||
)}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</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"
|
||
>
|
||
{selectedTemplate && !isEditMode ? 'Kapat' : 'İptal'}
|
||
</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">
|
||
{selectedQuestionGroup ? 'Soru Grubu Düzenle' : 'Yeni Soru Grubu'}
|
||
</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>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">Grup Adı</label>
|
||
<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>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">Açıklama</label>
|
||
<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">
|
||
Ağı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>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">Sıra</label>
|
||
<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">
|
||
{selectedQuestion ? 'Soru Düzenle' : 'Yeni Soru'}
|
||
</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>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">Soru Metni</label>
|
||
<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>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">Soru Tipi</label>
|
||
<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"
|
||
>
|
||
{Object.values(QuestionTypeEnum).map((type) => (
|
||
<option key={type} value={type}>
|
||
{getQuestionTypeText(type)}
|
||
</option>
|
||
))}
|
||
</select>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
Ağı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>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">Sıra</label>
|
||
<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"
|
||
/>
|
||
<label htmlFor="isRequired" className="ml-2 block text-sm text-gray-700">
|
||
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>
|
||
)}
|
||
</Container>
|
||
)
|
||
}
|
||
|
||
export default Degree360Templates
|