Add Orders and Order Status repositories with pagination and management features

- Implemented OrdersRepository for handling order data with pagination, filtering, and sorting capabilities.
- Added methods for retrieving order status options, quick stats, and detailed order information.
- Created OrderStatusRepository for managing order status groups and statuses, including CRUD operations and sorting.
- Introduced a bootstrap file for test environment setup and autoloading.
This commit is contained in:
2026-03-03 01:32:28 +01:00
parent d1576bc4ab
commit c489891d15
106 changed files with 11669 additions and 5091 deletions

View File

@@ -12,7 +12,7 @@ body {
body {
margin: 0;
font-family: "Roboto", "Segoe UI", sans-serif;
font-size: 14px;
font-size: 13px;
color: var(--c-text);
background: var(--c-bg);
}
@@ -127,7 +127,7 @@ a {
}
.topbar {
height: 56px;
height: 50px;
border-bottom: 1px solid var(--c-border);
background: var(--c-surface);
display: flex;
@@ -152,16 +152,16 @@ a {
.container {
max-width: none;
width: calc(100% - 28px);
margin: 18px 14px;
padding: 0 6px 24px;
width: calc(100% - 20px);
margin: 12px 10px;
padding: 0 4px 14px;
}
.card {
background: var(--c-surface);
border-radius: 10px;
box-shadow: var(--shadow-card);
padding: 24px;
padding: 14px;
}
.card h1 {
@@ -189,16 +189,16 @@ a {
.section-title {
margin: 0;
color: var(--c-text-strong);
font-size: 20px;
font-size: 18px;
font-weight: 700;
}
.mt-12 {
margin-top: 12px;
margin-top: 8px;
}
.mt-16 {
margin-top: 16px;
margin-top: 12px;
}
.settings-grid {
@@ -298,11 +298,169 @@ a {
flex-wrap: wrap;
}
.statuses-form {
display: grid;
gap: 8px;
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.statuses-color-input {
min-height: 32px;
padding: 2px;
}
.statuses-hint {
grid-column: 1 / -1;
margin: 0;
}
.statuses-group-block {
border: 1px solid var(--c-border);
border-radius: 10px;
padding: 8px;
background: #fbfdff;
}
.statuses-group-block__head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 6px;
flex-wrap: wrap;
}
.statuses-group-block__title {
margin: 0;
display: inline-flex;
align-items: center;
gap: 6px;
color: var(--c-text-strong);
font-size: 14px;
}
.statuses-color-dot {
width: 12px;
height: 12px;
border-radius: 999px;
border: 1px solid rgba(15, 23, 42, 0.15);
}
.statuses-dnd-list {
margin: 6px 0 0;
padding: 0;
list-style: none;
display: grid;
gap: 6px;
}
.statuses-dnd-item {
display: grid;
grid-template-columns: 24px 1fr;
gap: 6px;
border: 1px solid #dce4f0;
border-radius: 8px;
background: #fff;
padding: 6px;
}
.statuses-dnd-item__content {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
}
.statuses-dnd-item.is-dragging {
opacity: 0.6;
}
.statuses-dnd-item__drag {
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px dashed #cbd5e1;
border-radius: 6px;
color: #64748b;
cursor: grab;
user-select: none;
font-weight: 700;
font-size: 12px;
}
.statuses-dnd-item__drag:active {
cursor: grabbing;
}
.statuses-inline-form {
display: grid;
gap: 6px;
}
.statuses-inline-form--row {
grid-template-columns: minmax(180px, 1.4fr) minmax(150px, 1fr) auto auto auto;
align-items: center;
flex: 1 1 auto;
min-width: 0;
}
.statuses-inline-form--row-group {
grid-template-columns: minmax(180px, 1.5fr) 56px auto auto auto;
align-items: center;
flex: 1 1 auto;
min-width: 0;
}
.statuses-inline-form--row .form-control,
.statuses-inline-form--row-group .form-control {
min-height: 30px;
padding: 4px 8px;
}
.statuses-inline-form--row .btn,
.statuses-inline-form--row-group .btn,
.statuses-inline-delete .btn {
min-height: 30px;
padding: 4px 10px;
font-size: 12px;
}
.statuses-inline-check {
margin-top: 0;
white-space: nowrap;
font-size: 12px;
}
.statuses-inline-delete {
margin: 0;
flex: 0 0 auto;
}
.statuses-code-label {
font-size: 12px;
color: var(--c-muted);
}
.statuses-code-readonly {
display: inline-flex;
align-items: center;
gap: 6px;
white-space: nowrap;
font-size: 12px;
}
.statuses-code-readonly code {
background: #eef2f7;
border-radius: 6px;
padding: 1px 6px;
color: #1f2937;
font-size: 12px;
}
.field-inline {
display: flex;
align-items: center;
gap: 8px;
margin-top: 6px;
margin-top: 2px;
}
.modal-backdrop {
@@ -575,6 +733,592 @@ a {
width: 16px;
height: 16px;
}
.orders-page {
.orders-head {
background: linear-gradient(120deg, #f8fbff 0%, #eef5ff 100%);
border: 1px solid #dbe7fb;
}
.table-list {
border: 1px solid #dde5f2;
border-radius: 12px;
box-shadow: 0 6px 16px rgba(20, 44, 86, 0.08);
}
.table-list__header {
padding: 10px 6px 2px;
}
.table-list-filters {
padding: 6px 6px 2px;
border-top: 1px solid #ebf0f7;
border-bottom: 1px solid #ebf0f7;
background: #f9fbff;
}
.table-wrap {
border-radius: 10px;
overflow: hidden;
border: 1px solid #e7edf6;
}
.table thead th {
background: #f3f7fd;
color: #30435f;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.03em;
}
.table tbody td {
vertical-align: middle;
padding-top: 10px;
padding-bottom: 10px;
border-bottom-color: #edf2f8;
}
.table tbody tr:hover td {
background: #f9fcff;
}
}
.orders-list-page {
padding: 10px;
margin-bottom: 10px;
}
.orders-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
}
.orders-stats {
display: inline-grid;
grid-template-columns: repeat(3, minmax(86px, auto));
gap: 8px;
}
.orders-stat {
border: 1px solid #d8e2f0;
background: #f8fbff;
border-radius: 8px;
padding: 6px 8px;
line-height: 1.15;
&__label {
display: block;
color: #5f6f83;
font-size: 11px;
margin-bottom: 2px;
}
&__value {
color: #12233a;
font-size: 16px;
font-weight: 700;
}
}
.orders-ref {
display: grid;
gap: 2px;
min-width: 170px;
&__main {
font-weight: 700;
color: #0f1f35;
font-size: 14px;
}
&__meta {
display: inline-flex;
flex-wrap: wrap;
gap: 4px 10px;
color: #64748b;
font-size: 12px;
}
}
.orders-buyer {
display: grid;
gap: 2px;
&__name {
color: #0f172a;
font-weight: 600;
font-size: 14px;
}
&__meta {
display: inline-flex;
flex-wrap: wrap;
gap: 4px 10px;
color: #64748b;
font-size: 12px;
}
}
.orders-status-wrap {
display: inline-flex;
align-items: center;
gap: 5px;
flex-wrap: wrap;
}
.order-tag {
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid #d8e1ef;
background: #f8fafc;
color: #334155;
border-radius: 999px;
padding: 2px 8px;
font-size: 12px;
font-weight: 700;
line-height: 1.1;
&.is-info {
border-color: #bfdbfe;
background: #eff6ff;
color: #1d4ed8;
}
&.is-success {
border-color: #bbf7d0;
background: #f0fdf4;
color: #166534;
}
&.is-danger {
border-color: #fecaca;
background: #fef2f2;
color: #b91c1c;
}
&.is-warn {
border-color: #fde68a;
background: #fffbeb;
color: #92400e;
}
}
.orders-mini {
font-size: 14px;
color: #223247;
line-height: 1.25;
}
.orders-products {
display: grid;
gap: 4px;
min-width: 240px;
&__meta,
&__more {
font-size: 12px;
color: #64748b;
}
}
.orders-product {
display: grid;
grid-template-columns: 48px 1fr;
gap: 6px;
align-items: center;
&__thumb {
width: 48px;
height: 48px;
border-radius: 4px;
border: 1px solid #dbe3ef;
object-fit: cover;
background: #fff;
}
&__thumb--empty {
display: inline-block;
background: #eef2f7;
border-style: dashed;
}
&__txt {
min-width: 0;
display: grid;
gap: 1px;
}
&__name {
font-size: 14px;
color: #0f172a;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&__qty {
font-size: 12px;
color: #64748b;
}
}
.orders-image-trigger {
border: 0;
padding: 0;
margin: 0;
background: transparent;
cursor: zoom-in;
display: inline-flex;
align-items: center;
justify-content: center;
}
.orders-money {
display: grid;
gap: 2px;
&__main {
color: #0f172a;
font-weight: 700;
font-size: 14px;
}
&__meta {
color: #64748b;
font-size: 12px;
}
}
.table-list[data-table-list-id="orders"] {
gap: 8px;
.table-list__header {
padding: 2px 0 0;
}
.table-list-filters {
gap: 8px;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.table th,
.table td {
padding: 6px 8px;
}
.table thead th {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.02em;
white-space: nowrap;
}
.table tbody td {
vertical-align: top;
font-size: 14px;
line-height: 1.25;
}
}
.order-show-layout {
display: grid;
grid-template-columns: 220px minmax(0, 1fr);
gap: 12px;
align-items: start;
}
.order-statuses-side {
position: sticky;
top: 60px;
padding: 10px;
&__title {
font-size: 13px;
font-weight: 700;
color: #0f172a;
margin-bottom: 8px;
}
}
.order-status-group {
margin-bottom: 10px;
&__name {
font-size: 12px;
color: #475569;
font-weight: 700;
margin-bottom: 5px;
}
}
.order-status-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 4px 6px;
border-radius: 6px;
color: #334155;
font-size: 12px;
text-decoration: none;
&__count {
min-width: 24px;
text-align: center;
border-radius: 999px;
background: var(--status-color, #64748b);
padding: 1px 6px;
font-weight: 700;
font-size: 11px;
color: #ffffff;
}
}
.order-status-row:hover {
background: #f1f5f9;
}
.order-status-row.is-active {
background: rgba(15, 23, 42, 0.06);
color: #0f172a;
font-weight: 700;
}
.order-show-main {
min-width: 0;
}
.order-details-actions {
display: inline-flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 6px;
}
.order-details-page {
padding: 12px;
}
.order-details-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
}
.order-back-link {
color: #475569;
text-decoration: none;
font-weight: 600;
}
.order-back-link:hover {
color: #1d4ed8;
}
.order-details-sub {
display: inline-flex;
gap: 10px;
flex-wrap: wrap;
color: #64748b;
font-size: 12px;
}
.order-details-pill {
border-radius: 999px;
padding: 5px 10px;
background: #eef6ff;
border: 1px solid #cfe2ff;
color: #1d4ed8;
font-size: 12px;
font-weight: 700;
}
.order-details-tabs {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
.order-details-tab {
border: 1px solid #d6deea;
border-radius: 8px;
padding: 5px 10px;
color: #475569;
font-size: 12px;
background: #f8fafc;
cursor: pointer;
}
.order-details-tab.is-active {
border-color: #bfdbfe;
color: #1d4ed8;
background: #eff6ff;
font-weight: 700;
}
.order-item-cell {
display: grid;
grid-template-columns: 44px 1fr;
gap: 8px;
align-items: center;
min-width: 260px;
}
.order-item-thumb {
width: 44px;
height: 44px;
border-radius: 6px;
border: 1px solid #dbe3ef;
object-fit: cover;
}
.order-item-thumb--empty {
display: inline-block;
background: #eef2f7;
border-style: dashed;
}
.order-item-name {
font-weight: 600;
color: #0f172a;
}
.order-grid-2 {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.order-grid-3 {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
}
.order-kv {
margin: 0;
display: grid;
grid-template-columns: 150px 1fr;
gap: 6px 10px;
font-size: 12px;
}
.order-kv dt {
color: #64748b;
}
.order-kv dd {
margin: 0;
color: #0f172a;
font-weight: 600;
}
.order-address {
display: grid;
gap: 3px;
font-size: 12px;
color: #0f172a;
}
.order-events {
display: grid;
gap: 8px;
}
.order-event {
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 8px;
background: #fbfdff;
}
.order-event__head {
color: #64748b;
font-size: 11px;
}
.order-event__body {
margin-top: 4px;
color: #0f172a;
font-size: 12px;
}
.order-tab-panel {
display: none;
}
.order-tab-panel.is-active {
display: block;
}
.order-empty-placeholder {
border: 1px dashed #cbd5e1;
border-radius: 8px;
min-height: 180px;
background: #f8fafc;
}
.order-status-badge {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 4px 10px;
border-radius: 999px;
font-size: 12px;
font-weight: 700;
border: 1px solid #cbd5e1;
color: #334155;
background: #f8fafc;
&.is-info {
border-color: #bfdbfe;
background: #eff6ff;
color: #1d4ed8;
}
&.is-success {
border-color: #bbf7d0;
background: #f0fdf4;
color: #166534;
}
&.is-danger {
border-color: #fecaca;
background: #fef2f2;
color: #b91c1c;
}
&.is-warn {
border-color: #fde68a;
background: #fffbeb;
color: #92400e;
}
&.is-empty {
color: #94a3b8;
}
}
.order-buyer {
display: grid;
gap: 2px;
&__name {
color: #0f172a;
font-weight: 600;
}
&__email {
color: #64748b;
font-size: 12px;
}
}
.table-inline-action {
display: inline-block;
margin-right: 6px;
@@ -934,7 +1678,7 @@ a {
width: calc(100% - 16px);
margin-left: 8px;
margin-right: 8px;
padding: 0 4px 18px;
padding: 0 3px 12px;
}
.settings-grid {
@@ -946,14 +1690,52 @@ a {
align-items: flex-start;
}
.orders-stats {
grid-template-columns: 1fr;
width: 100%;
}
.order-show-layout {
grid-template-columns: 1fr;
}
.order-statuses-side {
position: static;
top: auto;
}
.order-details-actions {
justify-content: flex-start;
}
.order-grid-2,
.order-grid-3 {
grid-template-columns: 1fr;
}
.order-kv {
grid-template-columns: 1fr;
gap: 2px;
}
.filters-grid,
.form-grid,
.statuses-form,
.statuses-inline-form,
.table-list-filters,
.product-links-search-form,
.product-links-inline-form {
grid-template-columns: 1fr;
}
.statuses-dnd-item__content {
display: block;
}
.statuses-inline-delete {
margin-top: 6px;
}
.filters-actions {
align-items: center;
}
@@ -968,7 +1750,7 @@ a {
}
.card {
padding: 18px;
padding: 12px;
}
.modal--image-preview {

View File

@@ -16,8 +16,8 @@
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 38px;
padding: 8px 16px;
min-height: 34px;
padding: 6px 12px;
border: 1px solid transparent;
border-radius: 8px;
font: inherit;
@@ -74,10 +74,10 @@
.form-control {
width: 100%;
min-height: 38px;
min-height: 34px;
border: 1px solid var(--c-border);
border-radius: 8px;
padding: 7px 12px;
padding: 5px 10px;
font: inherit;
color: var(--c-text-strong);
background: #ffffff;
@@ -118,7 +118,7 @@
.form-field {
display: grid;
gap: 7px;
gap: 5px;
}
.field-label {