502 lines
20 KiB
HTML
502 lines
20 KiB
HTML
{% extends 'ssh_manager/base.html' %}
|
||
{% load static %}
|
||
|
||
{% block content %}
|
||
<style>
|
||
/* Alt menü stili */
|
||
.nav-pills .nav-link {
|
||
color: #e0e0e0;
|
||
border-radius: 5px;
|
||
padding: 0.5rem 1rem;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.nav-pills .nav-link:hover {
|
||
background-color: rgba(79, 195, 247, 0.1);
|
||
}
|
||
|
||
.nav-pills .nav-link.active {
|
||
background-color: #4fc3f7;
|
||
color: #212529;
|
||
}
|
||
|
||
/* Müşteri kartları */
|
||
.customer-card {
|
||
background: #23272b;
|
||
border: 1px solid #333;
|
||
border-radius: 8px;
|
||
padding: 1.5rem;
|
||
margin-bottom: 1rem;
|
||
transition: all 0.3s ease;
|
||
}
|
||
.customer-card:hover {
|
||
border-color: #4fc3f7;
|
||
box-shadow: 0 2px 8px rgba(79, 195, 247, 0.1);
|
||
}
|
||
.customer-type-badge {
|
||
font-size: 0.8rem;
|
||
padding: 0.25rem 0.75rem;
|
||
border-radius: 12px;
|
||
}
|
||
.customer-projects {
|
||
font-size: 0.9rem;
|
||
color: #bbb;
|
||
}
|
||
.action-buttons {
|
||
display: flex;
|
||
gap: 0.5rem;
|
||
justify-content: flex-end;
|
||
}
|
||
</style>
|
||
|
||
<!-- Alt Menü -->
|
||
<div class="mb-4 border-bottom pb-2">
|
||
<ul class="nav nav-pills">
|
||
<li class="nav-item">
|
||
<a href="{% url 'musteriler' %}" class="nav-link active">
|
||
<i class="bi bi-person-lines-fill"></i> Müşteri Listesi
|
||
</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a href="{% url 'faturalar' %}" class="nav-link text-light">
|
||
<i class="bi bi-receipt"></i> Faturalar
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||
<div>
|
||
<h3>Müşteri Yönetimi
|
||
{% if filter_type == 'individual' %}
|
||
<small class="text-muted">- Bireysel Müşteriler</small>
|
||
{% elif filter_type == 'corporate' %}
|
||
<small class="text-muted">- Kurumsal Müşteriler</small>
|
||
{% endif %}
|
||
</h3>
|
||
<small class="text-muted">Bireysel ve kurumsal müşteri profilleri</small>
|
||
</div>
|
||
<div class="d-flex gap-2">
|
||
<input type="text" id="customerSearch" class="form-control" style="max-width: 250px;" placeholder="Müşteri ara...">
|
||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#customerModal" onclick="resetCustomerForm()">
|
||
<i class="bi bi-plus-circle"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row">
|
||
{% for customer in customers %}
|
||
<div class="col-md-6 col-lg-4 customer-item" data-customer="{{ customer.get_display_name|lower }}">
|
||
<div class="customer-card">
|
||
<div class="d-flex justify-content-between align-items-start mb-2">
|
||
<div>
|
||
<h5 class="mb-1">{{ customer.get_display_name }}</h5>
|
||
<span class="customer-type-badge badge {% if customer.customer_type == 'corporate' %}bg-info{% else %}bg-success{% endif %}">
|
||
{% if customer.customer_type == 'corporate' %}Kurumsal{% else %}Bireysel{% endif %}
|
||
</span>
|
||
</div>
|
||
<div class="action-buttons">
|
||
<button class="btn btn-sm btn-outline-info" onclick="editCustomer({{ customer.id }})" title="Düzenle">
|
||
<i class="bi bi-pencil"></i>
|
||
</button>
|
||
<button class="btn btn-sm btn-outline-danger" onclick="deleteCustomer({{ customer.id }})" title="Sil">
|
||
<i class="bi bi-trash"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="customer-info">
|
||
{% if customer.email %}
|
||
<div class="mb-1">
|
||
<i class="bi bi-envelope me-1"></i>
|
||
<small>{{ customer.email }}</small>
|
||
</div>
|
||
{% endif %}
|
||
{% if customer.phone %}
|
||
<div class="mb-1">
|
||
<i class="bi bi-telephone me-1"></i>
|
||
<small>{{ customer.phone }}</small>
|
||
</div>
|
||
{% endif %}
|
||
{% if customer.customer_type == 'corporate' and customer.tax_number %}
|
||
<div class="mb-1">
|
||
<i class="bi bi-building me-1"></i>
|
||
<small>Vergi No: {{ customer.tax_number }}</small>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<div class="customer-projects mt-3">
|
||
<i class="bi bi-folder me-1"></i>
|
||
<small>{{ customer.project_set.count }} proje</small>
|
||
{% if customer.notes %}
|
||
<div class="mt-2">
|
||
<i class="bi bi-chat-text me-1"></i>
|
||
<small class="text-muted">{{ customer.notes|truncatechars:50 }}</small>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% empty %}
|
||
<div class="col-12">
|
||
<div class="text-center text-muted py-5">
|
||
<i class="bi bi-people" style="font-size: 3rem; opacity: 0.3;"></i>
|
||
<p class="mt-2">Henüz müşteri kaydı bulunmuyor</p>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
<!-- Müşteri Modal -->
|
||
<div class="modal fade" id="customerModal" tabindex="-1" aria-labelledby="customerModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<form id="customerForm">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="customerModalLabel">Yeni Müşteri Ekle</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<input type="hidden" id="customerId" name="customerId">
|
||
|
||
<!-- Müşteri Tipi Seçimi -->
|
||
<div class="mb-4">
|
||
<label class="form-label fw-bold">Müşteri Tipi</label>
|
||
<div class="d-flex gap-4 mt-2">
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="radio" name="customer_type" id="typeIndividual" value="individual" checked>
|
||
<label class="form-check-label" for="typeIndividual">
|
||
<i class="bi bi-person me-1"></i>Bireysel
|
||
</label>
|
||
</div>
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="radio" name="customer_type" id="typeCorporate" value="corporate">
|
||
<label class="form-check-label" for="typeCorporate">
|
||
<i class="bi bi-building me-1"></i>Kurumsal
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Bireysel Müşteri Alanları -->
|
||
<div id="individualFields">
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<label for="name" class="form-label">Ad *</label>
|
||
<input type="text" class="form-control" id="name" name="name">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="surname" class="form-label">Soyad *</label>
|
||
<input type="text" class="form-control" id="surname" name="surname">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="tc_number" class="form-label">TC Kimlik No</label>
|
||
<input type="text" class="form-control" id="tc_number" name="tc_number" maxlength="11" placeholder="11 haneli TC kimlik numarası">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="birth_date" class="form-label">Doğum Tarihi</label>
|
||
<input type="date" class="form-control" id="birth_date" name="birth_date">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Kurumsal Müşteri Alanları -->
|
||
<div id="corporateFields" style="display: none;">
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<label for="company_name" class="form-label">Şirket Adı *</label>
|
||
<input type="text" class="form-control" id="company_name" name="company_name">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="authorized_person" class="form-label">Yetkili Kişi</label>
|
||
<input type="text" class="form-control" id="authorized_person" name="authorized_person">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="tax_number" class="form-label">Vergi No</label>
|
||
<input type="text" class="form-control" id="tax_number" name="tax_number" placeholder="10 haneli vergi numarası">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="tax_office" class="form-label">Vergi Dairesi</label>
|
||
<input type="text" class="form-control" id="tax_office" name="tax_office">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- İletişim Bilgileri -->
|
||
<div class="mt-4">
|
||
<h6 class="text-muted mb-3">
|
||
<i class="bi bi-telephone me-1"></i>İletişim Bilgileri
|
||
</h6>
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<label for="email" class="form-label">E-posta *</label>
|
||
<input type="email" class="form-control" id="email" name="email" required placeholder="ornek@email.com">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="phone" class="form-label">Telefon</label>
|
||
<input type="tel" class="form-control" id="phone" name="phone" placeholder="0555 123 45 67">
|
||
</div>
|
||
<div class="col-12">
|
||
<label for="address" class="form-label">Adres</label>
|
||
<textarea class="form-control" id="address" name="address" rows="2" placeholder="Tam adres bilgisi..."></textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Ek Bilgiler -->
|
||
<div class="mt-4">
|
||
<h6 class="text-muted mb-3">
|
||
<i class="bi bi-chat-text me-1"></i>Ek Bilgiler
|
||
</h6>
|
||
<div class="row g-3">
|
||
<div class="col-12">
|
||
<label for="notes" class="form-label">Notlar</label>
|
||
<textarea class="form-control" id="notes" name="notes" rows="3" placeholder="Müşteri hakkında notlar, özel istekler vb."></textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Kapat</button>
|
||
<button type="submit" class="btn btn-primary">Kaydet</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// Müşteri tipi değiştiğinde alanları göster/gizle
|
||
document.querySelectorAll('input[name="customer_type"]').forEach(radio => {
|
||
radio.addEventListener('change', function() {
|
||
const individualFields = document.getElementById('individualFields');
|
||
const corporateFields = document.getElementById('corporateFields');
|
||
|
||
if (this.value === 'individual') {
|
||
individualFields.style.display = 'block';
|
||
corporateFields.style.display = 'none';
|
||
document.getElementById('name').required = true;
|
||
document.getElementById('surname').required = true;
|
||
document.getElementById('company_name').required = false;
|
||
} else {
|
||
individualFields.style.display = 'none';
|
||
corporateFields.style.display = 'block';
|
||
document.getElementById('name').required = false;
|
||
document.getElementById('surname').required = false;
|
||
document.getElementById('company_name').required = true;
|
||
}
|
||
});
|
||
});
|
||
|
||
// Müşteri arama
|
||
document.getElementById('customerSearch').addEventListener('keyup', function() {
|
||
const searchTerm = this.value.toLowerCase().trim();
|
||
const customerItems = document.querySelectorAll('.customer-item');
|
||
|
||
customerItems.forEach(item => {
|
||
const customerName = item.getAttribute('data-customer') || '';
|
||
if (searchTerm === '' || customerName.includes(searchTerm)) {
|
||
item.style.display = '';
|
||
} else {
|
||
item.style.display = 'none';
|
||
}
|
||
});
|
||
});
|
||
|
||
// Form reset
|
||
function resetCustomerForm() {
|
||
document.getElementById('customerForm').reset();
|
||
document.getElementById('customerId').value = '';
|
||
document.getElementById('customerModalLabel').textContent = 'Yeni Müşteri Ekle';
|
||
document.getElementById('typeIndividual').checked = true;
|
||
document.getElementById('individualFields').style.display = 'block';
|
||
document.getElementById('corporateFields').style.display = 'none';
|
||
document.getElementById('name').required = true;
|
||
document.getElementById('surname').required = true;
|
||
document.getElementById('company_name').required = false;
|
||
}
|
||
|
||
// Müşteri düzenle
|
||
function editCustomer(id) {
|
||
fetch(`/get-customer-details/${id}/`)
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
const customer = data.customer;
|
||
|
||
document.getElementById('customerId').value = id;
|
||
document.getElementById('customerModalLabel').textContent = 'Müşteri Düzenle';
|
||
|
||
// Müşteri tipini seç
|
||
if (customer.customer_type === 'corporate') {
|
||
document.getElementById('typeCorporate').checked = true;
|
||
document.getElementById('corporateFields').style.display = 'block';
|
||
document.getElementById('individualFields').style.display = 'none';
|
||
document.getElementById('name').required = false;
|
||
document.getElementById('surname').required = false;
|
||
document.getElementById('company_name').required = true;
|
||
} else {
|
||
document.getElementById('typeIndividual').checked = true;
|
||
document.getElementById('individualFields').style.display = 'block';
|
||
document.getElementById('corporateFields').style.display = 'none';
|
||
document.getElementById('name').required = true;
|
||
document.getElementById('surname').required = true;
|
||
document.getElementById('company_name').required = false;
|
||
}
|
||
|
||
// Form alanlarını doldur
|
||
document.getElementById('name').value = customer.name || '';
|
||
document.getElementById('surname').value = customer.surname || '';
|
||
document.getElementById('email').value = customer.email || '';
|
||
document.getElementById('phone').value = customer.phone || '';
|
||
document.getElementById('address').value = customer.address || '';
|
||
document.getElementById('notes').value = customer.notes || '';
|
||
document.getElementById('tc_number').value = customer.tc_number || '';
|
||
document.getElementById('birth_date').value = customer.birth_date || '';
|
||
document.getElementById('company_name').value = customer.company_name || '';
|
||
document.getElementById('authorized_person').value = customer.authorized_person || '';
|
||
document.getElementById('tax_number').value = customer.tax_number || '';
|
||
document.getElementById('tax_office').value = customer.tax_office || '';
|
||
|
||
const modal = new bootstrap.Modal(document.getElementById('customerModal'));
|
||
modal.show();
|
||
} else {
|
||
showToast('❌ Müşteri bilgisi alınamadı!', 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
showToast('❌ Müşteri bilgisi alınırken hata oluştu!', 'error');
|
||
});
|
||
}
|
||
|
||
// Müşteri sil
|
||
function deleteCustomer(id) {
|
||
if (confirm('Müşteriyi silmek istediğinizden emin misiniz?\nBu işlem müşteriye ait tüm projeleri de etkileyebilir.')) {
|
||
fetch(`/musteri/${id}/delete/`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'X-CSRFToken': getCookie('csrftoken'),
|
||
'Content-Type': 'application/json'
|
||
}
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
showToast('✅ Müşteri başarıyla silindi', 'success');
|
||
setTimeout(() => location.reload(), 1500);
|
||
} else {
|
||
showToast(`❌ ${data.message}`, 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
showToast('❌ Müşteri silme sırasında hata oluştu!', 'error');
|
||
});
|
||
}
|
||
}
|
||
|
||
// Form submit
|
||
document.getElementById('customerForm').addEventListener('submit', function(e) {
|
||
e.preventDefault();
|
||
|
||
const id = document.getElementById('customerId').value;
|
||
const url = id ? `/update-customer/${id}/` : '/musteri/create/';
|
||
const formData = new FormData(this);
|
||
|
||
fetch(url, {
|
||
method: 'POST',
|
||
headers: {
|
||
'X-CSRFToken': getCookie('csrftoken')
|
||
},
|
||
body: formData
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
showToast('✅ Müşteri başarıyla kaydedildi', 'success');
|
||
const modal = bootstrap.Modal.getInstance(document.getElementById('customerModal'));
|
||
if (modal) modal.hide();
|
||
setTimeout(() => location.reload(), 1500);
|
||
} else {
|
||
showToast(`❌ ${data.message}`, 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
showToast('❌ Müşteri kaydedilirken hata oluştu!', 'error');
|
||
});
|
||
});
|
||
|
||
// Cookie helper
|
||
function getCookie(name) {
|
||
let cookieValue = null;
|
||
if (document.cookie && document.cookie !== '') {
|
||
const cookies = document.cookie.split(';');
|
||
for (let i = 0; i < cookies.length; i++) {
|
||
const cookie = cookies[i].trim();
|
||
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
return cookieValue;
|
||
}
|
||
|
||
// Toast helper
|
||
function showToast(message, type = 'info') {
|
||
const toastBody = document.getElementById('mainToastBody');
|
||
const toastEl = document.getElementById('mainToast');
|
||
|
||
toastBody.textContent = message;
|
||
|
||
// Toast rengini ayarla
|
||
toastEl.className = 'toast align-items-center border-0';
|
||
if (type === 'success') {
|
||
toastEl.classList.add('text-bg-success');
|
||
} else if (type === 'error') {
|
||
toastEl.classList.add('text-bg-danger');
|
||
} else {
|
||
toastEl.classList.add('text-bg-info');
|
||
}
|
||
|
||
const toast = new bootstrap.Toast(toastEl);
|
||
toast.show();
|
||
}
|
||
|
||
// Sayfa yüklendiğinde URL parametrelerini kontrol et
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
const newCustomerType = urlParams.get('new');
|
||
|
||
if (newCustomerType && (newCustomerType === 'individual' || newCustomerType === 'corporate')) {
|
||
resetCustomerForm();
|
||
|
||
if (newCustomerType === 'corporate') {
|
||
document.getElementById('typeCorporate').checked = true;
|
||
document.getElementById('corporateFields').style.display = 'block';
|
||
document.getElementById('individualFields').style.display = 'none';
|
||
document.getElementById('name').required = false;
|
||
document.getElementById('surname').required = false;
|
||
document.getElementById('company_name').required = true;
|
||
} else {
|
||
document.getElementById('typeIndividual').checked = true;
|
||
document.getElementById('individualFields').style.display = 'block';
|
||
document.getElementById('corporateFields').style.display = 'none';
|
||
document.getElementById('name').required = true;
|
||
document.getElementById('surname').required = true;
|
||
document.getElementById('company_name').required = false;
|
||
}
|
||
|
||
const modal = new bootstrap.Modal(document.getElementById('customerModal'));
|
||
modal.show();
|
||
|
||
// URL'yi temizle
|
||
window.history.replaceState({}, document.title, window.location.pathname);
|
||
}
|
||
});
|
||
</script>
|
||
{% endblock %}
|