refactor: Update BillingManager UI components for improved styling and user experience, including badge colors, button styles, and status selection method.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m3s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m3s
This commit is contained in:
@@ -426,27 +426,32 @@ function BillingManager() {
|
||||
|
||||
if (days < 0) {
|
||||
return (
|
||||
<span className="badge bg-danger">
|
||||
Просрочено {Math.abs(days)} дн.
|
||||
<span className="badge bg-red-lt text-red">
|
||||
<IconAlertTriangle size={12} className="me-1" />
|
||||
{Math.abs(days)} дн. назад
|
||||
</span>
|
||||
);
|
||||
} else if (days === 0) {
|
||||
return <span className="badge bg-danger">Сегодня!</span>;
|
||||
return (
|
||||
<span className="badge bg-red-lt text-red">
|
||||
Сегодня
|
||||
</span>
|
||||
);
|
||||
} else if (days <= 7) {
|
||||
return (
|
||||
<span className="badge bg-warning text-dark">
|
||||
<span className="badge bg-yellow-lt text-yellow">
|
||||
{days} дн.
|
||||
</span>
|
||||
);
|
||||
} else if (days <= 30) {
|
||||
return (
|
||||
<span className="badge bg-blue-lt text-blue">
|
||||
<span className="badge bg-azure-lt text-azure">
|
||||
{days} дн.
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<span className="text-muted small">
|
||||
<span className="text-muted">
|
||||
{days} дн.
|
||||
</span>
|
||||
);
|
||||
@@ -495,7 +500,7 @@ function BillingManager() {
|
||||
<div className="card">
|
||||
<div className="card-body py-3">
|
||||
<div className="d-flex align-items-center">
|
||||
<span className="avatar avatar-md me-3 bg-primary-lt text-primary border-0">
|
||||
<span className="avatar avatar-md me-3 bg-blue-lt text-blue border-0">
|
||||
<IconCurrencyDollar size={24} />
|
||||
</span>
|
||||
<div>
|
||||
@@ -512,7 +517,7 @@ function BillingManager() {
|
||||
<div className="card">
|
||||
<div className="card-body py-3">
|
||||
<div className="d-flex align-items-center">
|
||||
<span className={`avatar avatar-md me-3 ${overduePayments.length > 0 ? 'bg-danger-lt text-danger' : 'bg-success-lt text-success'} border-0`}>
|
||||
<span className={`avatar avatar-md me-3 ${overduePayments.length > 0 ? 'bg-red-lt text-red' : 'bg-green-lt text-green'} border-0`}>
|
||||
<IconAlertTriangle size={24} />
|
||||
</span>
|
||||
<div>
|
||||
@@ -529,7 +534,7 @@ function BillingManager() {
|
||||
<div className="card">
|
||||
<div className="card-body py-3">
|
||||
<div className="d-flex align-items-center">
|
||||
<span className={`avatar avatar-md me-3 ${urgentPayments.length > 0 ? 'bg-warning-lt text-warning' : 'bg-blue-lt text-blue'} border-0`}>
|
||||
<span className={`avatar avatar-md me-3 ${urgentPayments.length > 0 ? 'bg-yellow-lt text-yellow' : 'bg-azure-lt text-azure'} border-0`}>
|
||||
<IconClock size={24} />
|
||||
</span>
|
||||
<div>
|
||||
@@ -568,21 +573,21 @@ function BillingManager() {
|
||||
</div>
|
||||
|
||||
{/* Быстрые фильтры */}
|
||||
<div className="btn-group btn-group-sm">
|
||||
<div className="d-flex gap-1">
|
||||
<button
|
||||
className={`btn ${filterUrgency === '' ? 'btn-primary' : 'btn-outline-primary'}`}
|
||||
className={`btn btn-sm ${filterUrgency === '' ? 'btn-primary' : 'btn-outline-secondary'}`}
|
||||
onClick={() => { setFilterUrgency(''); setCurrentPage(1); }}
|
||||
>
|
||||
Все
|
||||
</button>
|
||||
<button
|
||||
className={`btn ${filterUrgency === 'overdue' ? 'btn-danger' : 'btn-outline-danger'}`}
|
||||
className={`btn btn-sm ${filterUrgency === 'overdue' ? 'btn-red' : 'btn-outline-secondary'}`}
|
||||
onClick={() => { setFilterUrgency('overdue'); setCurrentPage(1); }}
|
||||
>
|
||||
Просрочено
|
||||
</button>
|
||||
<button
|
||||
className={`btn ${filterUrgency === 'urgent' ? 'btn-warning' : 'btn-outline-warning'}`}
|
||||
className={`btn btn-sm ${filterUrgency === 'urgent' ? 'btn-yellow' : 'btn-outline-secondary'}`}
|
||||
onClick={() => { setFilterUrgency('urgent'); setCurrentPage(1); }}
|
||||
>
|
||||
Срочно
|
||||
@@ -694,14 +699,16 @@ function BillingManager() {
|
||||
<UrgencyBadge days={days} />
|
||||
</td>
|
||||
<td className="text-center">
|
||||
<span className={`badge ${item.status === 'active' ? 'bg-success-lt text-success' : 'bg-secondary-lt text-secondary'}`}>
|
||||
{item.status === 'active' ? '●' : '○'}
|
||||
</span>
|
||||
{item.status === 'active' ? (
|
||||
<span className="badge bg-green-lt text-green">Активен</span>
|
||||
) : (
|
||||
<span className="badge bg-secondary-lt text-secondary">Неактивен</span>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<div className="btn-list gap-1 justify-content-end">
|
||||
<div className="btn-list gap-1 justify-content-end flex-nowrap">
|
||||
<button
|
||||
className="btn btn-ghost-success btn-icon btn-sm"
|
||||
className="btn btn-icon btn-sm btn-outline-success"
|
||||
onClick={() => {
|
||||
setPaymentDraft({
|
||||
serverId: item.id,
|
||||
@@ -717,14 +724,14 @@ function BillingManager() {
|
||||
<IconCreditCard size={16} />
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-ghost-primary btn-icon btn-sm"
|
||||
className="btn btn-icon btn-sm btn-outline-primary"
|
||||
onClick={() => handleEditItem(item)}
|
||||
title="Редактировать"
|
||||
>
|
||||
<IconEdit size={16} />
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-ghost-danger btn-icon btn-sm"
|
||||
className="btn btn-icon btn-sm btn-outline-danger"
|
||||
onClick={() => handleDeleteItem(item)}
|
||||
title="Удалить"
|
||||
>
|
||||
@@ -830,9 +837,9 @@ function BillingManager() {
|
||||
</td>
|
||||
<td className="text-muted small">{r.note || '—'}</td>
|
||||
<td>
|
||||
<div className="btn-list gap-1 justify-content-end">
|
||||
<div className="btn-list gap-1 justify-content-end flex-nowrap">
|
||||
<button
|
||||
className="btn btn-ghost-primary btn-icon btn-sm"
|
||||
className="btn btn-icon btn-sm btn-outline-secondary"
|
||||
onClick={() => {
|
||||
setPaymentDraft({
|
||||
serverId: r.server.id,
|
||||
@@ -849,7 +856,7 @@ function BillingManager() {
|
||||
<IconEdit size={14} />
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-ghost-danger btn-icon btn-sm"
|
||||
className="btn btn-icon btn-sm btn-outline-danger"
|
||||
onClick={() => {
|
||||
setPaymentToDelete({ serverId: r.server.id, index: r._index, data: r });
|
||||
setShowDeletePaymentModal(true);
|
||||
@@ -1077,21 +1084,35 @@ function BillingForm({ item, onItemChange, servers }) {
|
||||
|
||||
<div className="col-12">
|
||||
<div className="form-label">Статус</div>
|
||||
<div className="btn-group w-100">
|
||||
<button
|
||||
type="button"
|
||||
className={`btn ${item.status === 'active' ? 'btn-success' : 'btn-outline-success'}`}
|
||||
onClick={() => onItemChange({ ...item, status: 'active' })}
|
||||
>
|
||||
Активен
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`btn ${item.status === 'inactive' ? 'btn-secondary' : 'btn-outline-secondary'}`}
|
||||
onClick={() => onItemChange({ ...item, status: 'inactive' })}
|
||||
>
|
||||
Неактивен
|
||||
</button>
|
||||
<div className="d-flex gap-2">
|
||||
<label className="form-selectgroup-item flex-fill">
|
||||
<input
|
||||
type="radio"
|
||||
name="status"
|
||||
value="active"
|
||||
className="form-selectgroup-input"
|
||||
checked={item.status === 'active'}
|
||||
onChange={() => onItemChange({ ...item, status: 'active' })}
|
||||
/>
|
||||
<span className="form-selectgroup-label">
|
||||
<IconCheck size={16} className="me-1" />
|
||||
Активен
|
||||
</span>
|
||||
</label>
|
||||
<label className="form-selectgroup-item flex-fill">
|
||||
<input
|
||||
type="radio"
|
||||
name="status"
|
||||
value="inactive"
|
||||
className="form-selectgroup-input"
|
||||
checked={item.status === 'inactive'}
|
||||
onChange={() => onItemChange({ ...item, status: 'inactive' })}
|
||||
/>
|
||||
<span className="form-selectgroup-label">
|
||||
<IconX size={16} className="me-1" />
|
||||
Неактивен
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user