feat: Implement campaign synchronization feature with dropdown UI

- Updated SCSS styles for new campaign sync buttons and dropdowns.
- Refactored main_view.php to replace the single select for campaigns with a multi-select dropdown.
- Added JavaScript functions to handle dropdown interactions and sync status updates.
- Introduced sync status bars for clients in main_view.php.
- Created new database migrations for client sync flags and cron sync status tracking.
This commit is contained in:
2026-02-19 12:33:14 +01:00
parent bfbcb1c871
commit 38082c5bac
13 changed files with 1039 additions and 838 deletions

View File

@@ -38,7 +38,7 @@ body {
color: $cText;
background: $cContentBg;
max-width: 100vw;
overflow: hidden;
overflow-x: hidden;
}
.hide {
@@ -1168,6 +1168,78 @@ table {
color: $cWhite;
}
}
&.btn-icon-sync {
background: #F0FDF4;
color: #16a34a;
&:hover {
background: #16a34a;
color: $cWhite;
}
&:disabled {
opacity: 0.7;
cursor: wait;
}
&.is-queued {
background: #FEF3C7;
color: #D97706;
}
}
}
.client-sync-bars {
display: flex;
flex-direction: column;
gap: 4px;
}
.client-sync-row {
display: flex;
align-items: center;
gap: 4px;
}
.client-sync-label {
font-size: 11px;
font-weight: 600;
color: #8899A6;
width: 18px;
flex-shrink: 0;
}
.client-sync-track {
flex: 1;
height: 6px;
border-radius: 999px;
background: #E9EEF5;
overflow: hidden;
}
.client-sync-fill {
height: 100%;
border-radius: 999px;
background: #CBD5E0;
transition: width 0.4s ease;
&.is-active {
background: linear-gradient(90deg, #5A9BFF 0%, #2E6BDF 100%);
}
&.is-done {
background: $cSuccess;
}
}
.client-sync-pct {
font-size: 11px;
font-weight: 600;
color: #8899A6;
width: 32px;
text-align: right;
flex-shrink: 0;
}
.empty-state {
@@ -1279,6 +1351,7 @@ table {
.filter-with-action {
display: flex;
align-items: center;
gap: 8px;
.form-control {
@@ -1310,6 +1383,121 @@ table {
}
}
}
.filter-group-campaign-multi {
flex: 2 !important;
}
.campaign-dropdown {
flex: 1;
min-width: 0;
position: relative;
}
.campaign-dropdown-trigger {
width: 100%;
padding: 10px 14px;
padding-right: 32px;
border: 1px solid $cBorder;
border-radius: 8px;
font-size: 14px;
color: $cTextDark;
background: $cWhite;
cursor: pointer;
display: flex;
align-items: center;
transition: border-color 0.2s;
position: relative;
min-height: 42px;
box-sizing: border-box;
.campaign-dropdown-text {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&.is-placeholder {
color: #8899A6;
}
}
.campaign-dropdown-arrow {
position: absolute;
right: 12px;
font-size: 10px;
color: #8899A6;
transition: transform 0.2s;
}
}
.campaign-dropdown.is-open {
.campaign-dropdown-trigger {
border-color: $cPrimary;
box-shadow: 0 0 0 3px rgba($cPrimary, 0.1);
}
.campaign-dropdown-arrow {
transform: rotate(180deg);
}
.campaign-dropdown-menu {
display: block;
}
}
.campaign-dropdown-menu {
display: none;
position: absolute;
top: calc(100% + 4px);
left: 0;
right: 0;
z-index: 100;
max-height: 280px;
overflow-y: auto;
background: $cWhite;
border: 1px solid $cBorder;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
padding: 4px 0;
}
.campaign-dropdown-item {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
cursor: pointer;
font-size: 14px;
color: $cTextDark;
margin: 0;
transition: background 0.15s;
&:hover {
background: #F8FAFC;
}
&.is-checked {
background: #EEF2FF;
}
input[type="checkbox"] {
width: 16px;
height: 16px;
cursor: pointer;
flex-shrink: 0;
accent-color: $cPrimary;
}
span {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.campaigns-list-panel {