From f8ce4baa7af9ed930a2ae9919414e6387c33f186 Mon Sep 17 00:00:00 2001 From: Scheianu Ionut Date: Sun, 14 Sep 2025 14:46:21 +0300 Subject: [PATCH] update pages --- py_app/app/__pycache__/routes.cpython-312.pyc | Bin 24992 -> 26925 bytes py_app/app/routes.py | 33 ++- py_app/app/static/script.js | 152 ++++++++++ py_app/app/static/style.css | 262 ++++++++++++++++++ py_app/app/templates/dashboard.html | 26 +- py_app/app/templates/quality.html | 103 +++++-- py_app/app/templates/scan.html | 2 +- 7 files changed, 538 insertions(+), 40 deletions(-) diff --git a/py_app/app/__pycache__/routes.cpython-312.pyc b/py_app/app/__pycache__/routes.cpython-312.pyc index 6338d3a2413e8b1677db63ae8199bfed631f4e61..491eb8578e0e1f166c948cfcdae4c0e0a98c1387 100644 GIT binary patch delta 1949 zcmZ{kdrVVT9LMju?X9H`XiK3y^$IA~A!fRWAPgA@itzrQi2wxrbQcpUt=ztfvA0x6vJw)6|5WuZsd-)@*B(>ZCoqvxawKn#>)uS*#cB(tr6# zY5tF>o1_)2N3z^r;A7cB1sPtSDGwA@BcoxtLu?eWO%kiI*yO|#=}e1ckFjK_W)-=c zrX#7E6{KXLW^pTWFb+mg9A{hE5Js9uOZ7j&VYMneiuw>@G{u-(l^#Y=zPf}q)9yid zuSZ$0CC{6}!#NMCLBUBQhT8S8A*Gd*!h-Pxl?U}Q!n_j-4>!A%W>%j<9##k;Lu;P1 z7=x=l^CVMHOJ?HDh(H$N&RV8r1x+S((3+wl#bU(FNn!A?v!SI0!2lkX+<%d8OJt;& zps7ACsAhkY7`(7mJtv&jqwZx+(0dkGgBU^Q??F#{V1-bqV=E(swW{~3-z^LLwxAZ~ z4aHWb1zC;m^nzzcz{3%&#S&lR#JsCXwAa)9mZy+S+*X^I8irN#_S(8e2S0axAXNtMUO<}iW7_=1&7f3#hHfl&C+E%y9asu!Z2T?}0%1{V#*Lzo zVKv|o$axm98ITL808|3pfD%AIKmkw!1^`un42m|q2c(|D8scw%O79XI{FlEPMujhc zzZ&2V-VJIe;1a+_;etx|;DZzB+f>-U{s(xFT6fYTb!AetGmlhEXvCrI``WhO*2jx^UOHG@Ti*_zRWF;mf~bW>MO=C6N=3>2EeS6(c?smz$xnmS)NkTs@^`tyPD z@W#kCnpv$MGpxLrb8+QZXxdHn>dBb&!DWLBM$uSQVTZD#;-LPqk7H?xGp;P!?l70b z=S4D?7lq^*RF_ki=4o{!Q5@AH@fK>oq6K}$paLBkzD}dKVzsQ}6jwQpYIn$TQL3}o zijruju^2{<--M9nQ>rkajVvh|;y$P9ZE~-uoBM*Q{p6kEK5mGrgJfw*pJs%r!*twu znA|8i#$BVY?~~U`51^~$X(`WLr|-Qaq3j6yihNcU%Y9AXz2w_6U;6B=@?Q)Vk5d=E zMd5-EJI@CWS?ds`YP++cd3U1=e?uLoW#yIxgf5We^7-5pHT27c<=?Xw*y;G`&iR?` z{i?N7DwkxVt>Gb(Tk)Y~lKQ69O+rm|lTE6%h6e8S9r9O2rNMvqrs)EF7jTO>D&OQD zQu&d5zj6Sj{07!vDO|Km=2=w+I~L&s+~Bm+G)`LDAJln^j8+lt@37%9V20FeTf{w~ za*A|ri$i&G|F&#YAcGI?s(;8B=8IvpcnAOk#V|$;v%@ejf8Q8-#ZZ_(7k)xgcf@N{ tv?!>{<&a@yzX5tI8zuk% delta 651 zcmYL_Ur1AN6vuZi`%T;2&}bEvHl>maKJ*kNgxO%W0x4@b6}Guu+o0*}H^qV;vWI$5 z1UZ_2g4IJ&q!Y%E5-Vg_R4A-cBasg9bpDNwh}TcOx+MqzsUl!lK)4Vm~^wEp*MEne7%1#lLf zG`3NvhAB&<`3mTb>OfKcFzBk}SO`GJ&iXzJ(iSq9?ND=IVw*cMsT9x1Z31&LqUVfnDri2rKf_RE}bm{ ztKtEc5DuQpipNAzJmVV`vqTs1t1l(yh!Qw-K4pDQlmr@hiiesfMV87wTx}kJd2IK) z!~)e<@rHjKUgO@D-Qo?^{aDvhIP#E4HnG@AbWJWY=SY$oiOVIc==I4K?dS>qI;C1nha8xygX29};-S21#SBjs6Pp~G8wgQ{KS$^SScz@M8;WN5A z=^(gf%A0FH+NxJ<`a82OE6LK`sw`3m$1^;#kte4pIY7zTNsdisSvVodv20u?`69`` cBYC@A$1$Va`j?QlnUZcbZ`{#Te{>rD0sL{o?*IS* diff --git a/py_app/app/routes.py b/py_app/app/routes.py index 2c8455f..b9d47a3 100644 --- a/py_app/app/routes.py +++ b/py_app/app/routes.py @@ -338,7 +338,7 @@ def get_report_data(): """) rows = cursor.fetchall() print("Fetched rows for report 5 (all rows):", rows) - data["headers"] = ["Id", "Operator Code", "CP Base Code", "CP Full Code", "OC1 Code", "OC2 Code", "Quality Code", "Date", "Time", "Approved Quantity", "Rejected Quantity"] + data["headers"] = ["Id", "Operator Code", "CP Base Code", "CP Full Code", "OC1 Code", "OC2 Code", "Quality Code", "Date", "Time", "Approved Quantity of order", "Rejected Quantity of order"] data["rows"] = [[str(cell) if isinstance(cell, (datetime, timedelta)) else cell for cell in row] for row in rows] conn.close() @@ -349,6 +349,37 @@ def get_report_data(): print("Data being returned:", data) return jsonify(data) +@bp.route('/generate_report', methods=['GET']) +def generate_report(): + """Generate report for specific date (calendar-based report)""" + report = request.args.get('report') + selected_date = request.args.get('date') + data = {"headers": [], "rows": []} + + try: + conn = get_db_connection() + cursor = conn.cursor() + + if report == "6" and selected_date: # Custom date report + cursor.execute(""" + SELECT Id, operator_code, CP_base_code, OC1_code, OC2_code, quality_code, date, time, approved_quantity, rejected_quantity + FROM scan1_orders + WHERE date = ? + ORDER BY time DESC + """, (selected_date,)) + rows = cursor.fetchall() + print(f"Fetched rows for report 6 (custom date {selected_date}):", rows) + data["headers"] = ["Id", "Operator Code", "CP Base Code", "OC1 Code", "OC2 Code", "Quality Code", "Date", "Time", "Approved Quantity", "Rejected Quantity"] + data["rows"] = [[str(cell) if isinstance(cell, (datetime, timedelta)) else cell for cell in row] for row in rows] + + conn.close() + except mariadb.Error as e: + print(f"Error fetching custom date report: {e}") + data["error"] = f"Error fetching report data for {selected_date}." + + print("Custom date report data being returned:", data) + return jsonify(data) + @bp.route('/etichete') def etichete(): if 'role' not in session or session['role'] not in ['superadmin', 'etichete']: diff --git a/py_app/app/static/script.js b/py_app/app/static/script.js index c18d610..5a724d6 100644 --- a/py_app/app/static/script.js +++ b/py_app/app/static/script.js @@ -284,4 +284,156 @@ document.addEventListener('DOMContentLoaded', () => { draggingField.style.top = `${e.clientY - rect.top}px`; }); } + + // Calendar functionality for date selection + const selectDayReportBtn = document.getElementById('select-day-report'); + const calendarModal = document.getElementById('calendar-modal'); + const closeModal = document.querySelector('.close-modal'); + const cancelDate = document.getElementById('cancel-date'); + const confirmDate = document.getElementById('confirm-date'); + const calendarDays = document.getElementById('calendar-days'); + const calendarMonthYear = document.getElementById('calendar-month-year'); + const prevMonth = document.getElementById('prev-month'); + const nextMonth = document.getElementById('next-month'); + + let currentDate = new Date(); + let selectedDate = null; + + // Show calendar modal + if (selectDayReportBtn) { + selectDayReportBtn.addEventListener('click', () => { + calendarModal.style.display = 'block'; + generateCalendar(currentDate); + }); + } + + // Close modal events + if (closeModal) { + closeModal.addEventListener('click', closeCalendarModal); + } + if (cancelDate) { + cancelDate.addEventListener('click', closeCalendarModal); + } + + // Click outside modal to close + window.addEventListener('click', (e) => { + if (e.target === calendarModal) { + closeCalendarModal(); + } + }); + + // Navigation buttons + if (prevMonth) { + prevMonth.addEventListener('click', () => { + currentDate.setMonth(currentDate.getMonth() - 1); + generateCalendar(currentDate); + }); + } + + if (nextMonth) { + nextMonth.addEventListener('click', () => { + currentDate.setMonth(currentDate.getMonth() + 1); + generateCalendar(currentDate); + }); + } + + // Confirm date selection + if (confirmDate) { + confirmDate.addEventListener('click', () => { + if (selectedDate) { + // Format date as YYYY-MM-DD + const formattedDate = selectedDate.toISOString().split('T')[0]; + closeCalendarModal(); + + // Fetch report data for the selected date + fetchCustomDateReport(formattedDate); + } + }); + } + + function closeCalendarModal() { + calendarModal.style.display = 'none'; + selectedDate = null; + confirmDate.disabled = true; + + // Remove selected class from all days + const selectedDays = document.querySelectorAll('.calendar-day.selected'); + selectedDays.forEach(day => day.classList.remove('selected')); + } + + function generateCalendar(date) { + const year = date.getFullYear(); + const month = date.getMonth(); + + // Update header + const monthNames = ['January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December']; + calendarMonthYear.textContent = `${monthNames[month]} ${year}`; + + // Clear previous days + calendarDays.innerHTML = ''; + + // Get first day of month and number of days + const firstDay = new Date(year, month, 1).getDay(); + const daysInMonth = new Date(year, month + 1, 0).getDate(); + const today = new Date(); + + // Add empty cells for days before month starts + for (let i = 0; i < firstDay; i++) { + const emptyDay = document.createElement('div'); + emptyDay.classList.add('calendar-day', 'other-month'); + calendarDays.appendChild(emptyDay); + } + + // Add days of the month + for (let day = 1; day <= daysInMonth; day++) { + const dayElement = document.createElement('div'); + dayElement.classList.add('calendar-day'); + dayElement.textContent = day; + + const dayDate = new Date(year, month, day); + + // Highlight today + if (dayDate.toDateString() === today.toDateString()) { + dayElement.classList.add('today'); + } + + // Add click event + dayElement.addEventListener('click', () => { + // Remove previous selection + const previousSelected = document.querySelector('.calendar-day.selected'); + if (previousSelected) { + previousSelected.classList.remove('selected'); + } + + // Select this day + dayElement.classList.add('selected'); + selectedDate = new Date(year, month, day); + confirmDate.disabled = false; + }); + + calendarDays.appendChild(dayElement); + } + } + + function fetchCustomDateReport(dateString) { + reportTitle.textContent = `Loading report for ${dateString}...`; + + fetch(`/generate_report?report=6&date=${dateString}`) + .then(response => response.json()) + .then(data => { + if (data.error) { + reportTitle.textContent = `Error: ${data.error}`; + populateTable({ headers: [], rows: [] }); + } else { + reportTitle.textContent = `Daily Report for ${dateString}`; + populateTable(data); + } + }) + .catch(error => { + console.error('Error fetching custom date report:', error); + reportTitle.textContent = 'Error loading report'; + populateTable({ headers: [], rows: [] }); + }); + } }); \ No newline at end of file diff --git a/py_app/app/static/style.css b/py_app/app/static/style.css index 951f41f..7dcb100 100644 --- a/py_app/app/static/style.css +++ b/py_app/app/static/style.css @@ -678,6 +678,99 @@ body.dark-mode .export-description { border: 1px solid #ddd; /* Add borders to table cells */ } +/* Reports Grid Layout - Label and Button Side by Side */ +.reports-grid { + display: flex; + flex-direction: column; + gap: 8px; /* Reduced spacing between report rows */ + margin-bottom: 25px; /* More space before separator */ +} + +.report-column { + display: flex; + flex-direction: column; + gap: 8px; +} + +/* Specific styles for Quality Reports Card ONLY */ +.report-form-card .form-centered { + display: grid; + grid-template-columns: 2fr 1fr; + gap: 15px; + align-items: center; + padding: 6px 0; /* Reduced vertical padding */ +} + +.report-form-card .form-centered .report-description { + margin: 0; + padding-right: 10px; + font-size: 0.85em; /* Smaller text for quality reports */ + line-height: 1.3; +} + +.report-form-card .form-centered .btn { + margin: 0; + white-space: nowrap; + font-size: 0.8em; /* Smaller button text for quality reports */ + padding: 8px 12px; /* Adjust padding for smaller text */ +} + +/* Keep original form-centered styles for other pages */ +.form-centered:not(.report-form-card .form-centered) { + display: flex; + flex-direction: column; + align-items: center; + margin: 20px 0; +} + +/* Separator between reports and export section */ +.report-separator { + width: 100%; + height: 2px; + background: linear-gradient(to right, #ddd, #999, #ddd); + margin: 25px 0 20px 0; /* More space above, good space below */ + border-radius: 1px; +} + +/* Export section styling - specific to quality reports */ +.export-section { + padding-top: 5px; + margin-bottom: 15px; /* Add space at bottom of card */ +} + +.report-form-card .export-section .export-description { + font-size: 0.85em; /* Smaller export label text */ + margin-bottom: 8px; /* Reduced margin */ +} + +.report-form-card .export-section .btn { + font-size: 0.8em; /* Smaller export button text */ + padding: 8px 12px; +} + +.report-form-card .export-section .form-centered.last-buttons { + padding: 5px 0; /* Reduced padding for export section */ +} + +/* Responsive design for Quality Reports Card only */ +@media (max-width: 768px) { + .report-form-card .form-centered { + grid-template-columns: 1fr; + gap: 10px; + text-align: center; + } + + .report-form-card .form-centered .report-description { + padding-right: 0; + margin-bottom: 5px; + font-size: 0.8em; /* Even smaller on mobile */ + } + + .report-form-card .form-centered .btn { + font-size: 0.75em; /* Smaller buttons on mobile */ + } +} + .go-to-main-etichete-btn { background-color: #28a745; /* Green background */ color: #fff; /* White text */ @@ -721,4 +814,173 @@ body.dark-mode .export-description { position: relative; background-color: #f8f9fa; /* Light gray background */ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Subtle shadow for better visibility */ +} + +/* Calendar Modal Styles */ +.modal { + display: none; + position: fixed; + z-index: 1000; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.5); +} + +.modal-content { + background-color: #fefefe; + margin: 5% auto; + padding: 0; + border-radius: 8px; + width: 400px; + max-width: 90%; + box-shadow: 0 4px 20px rgba(0,0,0,0.3); +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 15px 20px; + background-color: #f8f9fa; + border-radius: 8px 8px 0 0; + border-bottom: 1px solid #ddd; +} + +.modal-header h4 { + margin: 0; + color: #333; +} + +.close-modal { + font-size: 24px; + font-weight: bold; + cursor: pointer; + color: #666; + line-height: 1; +} + +.close-modal:hover { + color: #333; +} + +.modal-body { + padding: 20px; +} + +.modal-footer { + display: flex; + justify-content: flex-end; + gap: 10px; + padding: 15px 20px; + border-top: 1px solid #ddd; + border-radius: 0 0 8px 8px; + background-color: #f8f9fa; +} + +/* Calendar Styles */ +.calendar-container { + width: 100%; +} + +.calendar-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; +} + +.calendar-header h3 { + margin: 0; + color: #333; + font-size: 1.1em; +} + +.calendar-nav { + background: none; + border: 1px solid #ddd; + border-radius: 4px; + padding: 5px 10px; + cursor: pointer; + font-size: 14px; + color: #666; +} + +.calendar-nav:hover { + background-color: #f0f0f0; + color: #333; +} + +.calendar-grid { + width: 100%; +} + +.calendar-weekdays { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 2px; + margin-bottom: 5px; +} + +.calendar-weekdays div { + padding: 8px 4px; + text-align: center; + font-weight: bold; + font-size: 0.85em; + color: #666; + background-color: #f8f9fa; +} + +.calendar-days { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 2px; +} + +.calendar-day { + padding: 10px 4px; + text-align: center; + cursor: pointer; + border-radius: 4px; + font-size: 0.9em; + min-height: 35px; + display: flex; + align-items: center; + justify-content: center; +} + +.calendar-day:hover { + background-color: #e9ecef; +} + +.calendar-day.other-month { + color: #ccc; +} + +.calendar-day.today { + background-color: #007bff; + color: white; +} + +.calendar-day.selected { + background-color: #28a745; + color: white; +} + +.calendar-day.selected:hover { + background-color: #218838; +} + +/* Responsive Calendar */ +@media (max-width: 480px) { + .modal-content { + margin: 10% auto; + width: 95%; + } + + .calendar-day { + min-height: 30px; + font-size: 0.8em; + } } \ No newline at end of file diff --git a/py_app/app/templates/dashboard.html b/py_app/app/templates/dashboard.html index c0ce2d5..c118aff 100644 --- a/py_app/app/templates/dashboard.html +++ b/py_app/app/templates/dashboard.html @@ -7,28 +7,28 @@
-

Accesare modul scanare

-

Modul de scanare finala a comenzilor de productie

- Lansare modul de scanare +

Access Scanning Module

+

Final scanning module for production orders

+ Launch Scanning Module
-

Accesare modul calitate

-

Modul de verificare si configurare setari calitate.

- Lansare modul calitate +

Access Reports Module

+

Module for verification and quality settings configuration.

+ Launch Reports Module
-

Accesare modul magazie

-

Acceseaza functionalitatile modulului de magazie.

- Deschide magazie +

Access Warehouse Module

+

Access warehouse module functionalities.

+ Open Warehouse
- +
-

Accesare modul Etichete

-

Modul pentru gestionarea etichetelor.

- Lansare modul Etichete +

Access Labels Module

+

Module for label management.

+ Launch Labels Module
diff --git a/py_app/app/templates/quality.html b/py_app/app/templates/quality.html index bce10c5..64f64c0 100644 --- a/py_app/app/templates/quality.html +++ b/py_app/app/templates/quality.html @@ -4,32 +4,47 @@
-

Rapoarte

-
- - +

Reports

+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
-
- - -
-
- - -
-
- - -
-
- - -
-
- -
- - + + +
+ + +
+
+ +
+ + +
@@ -51,5 +66,43 @@
+ + + + {% endblock %} diff --git a/py_app/app/templates/scan.html b/py_app/app/templates/scan.html index c39af97..080043c 100644 --- a/py_app/app/templates/scan.html +++ b/py_app/app/templates/scan.html @@ -6,7 +6,7 @@

Scan Input

- +