diff --git a/client/src/components/ViolationHistory.jsx b/client/src/components/ViolationHistory.jsx index 7b48107..5847720 100755 --- a/client/src/components/ViolationHistory.jsx +++ b/client/src/components/ViolationHistory.jsx @@ -1,63 +1 @@ -import React, { useState } from 'react'; - -const s = { - wrapper: { marginTop: '24px' }, - title: { color: '#b5b5c0', fontSize: '16px', fontWeight: 700, marginBottom: '10px' }, - table: { width: '100%', borderCollapse: 'collapse', fontSize: '13px', background: '#111217', borderRadius: '6px', overflow: 'hidden', border: '1px solid #222' }, - th: { background: '#000000', color: '#f8f9fa', padding: '8px 10px', textAlign: 'left', fontSize: '12px', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.5px' }, - td: { padding: '8px 10px', borderBottom: '1px solid #1c1d29', color: '#f8f9fa', verticalAlign: 'middle' }, - trEven: { background: '#111217' }, - trOdd: { background: '#151622' }, - pts: { fontWeight: 700, color: '#667eea' }, - toggle: { background: 'none', border: 'none', color: '#667eea', cursor: 'pointer', fontSize: '13px', padding: 0, textDecoration: 'underline' }, - empty: { color: '#77798a', fontStyle: 'italic', fontSize: '13px', marginTop: '8px' }, -}; - -function formatDate(d) { - if (!d) return '–'; - const dt = new Date(d + 'T12:00:00'); - return dt.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', timeZone: 'America/Chicago' }); -} - -export default function ViolationHistory({ history, loading }) { - const [expanded, setExpanded] = useState(false); - const visible = expanded ? history : history.slice(0, 5); - - if (loading) return

Loading history...

; - if (!history.length) return

No violations on record for this employee.

; - - return ( -
-
Recent Violations ({history.length} total)
- - - - - - - - - - - - {visible.map((v, i) => ( - - - - - - - - ))} - -
DateViolationCategoryPointsDetails
{formatDate(v.incident_date)}{v.violation_name}{v.category}{v.points}{v.details || '–'}
- {history.length > 5 && ( -
- -
- )} -
- ); -} +aW1wb3J0IFJlYWN0LCB7IHVzZVN0YXRlIH0gZnJvbSAncmVhY3QnOwppbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnOwoKY29uc3QgcyA9IHsKICB3cmFwcGVyOiAgeyBtYXJnaW5Ub3A6ICcyNHB4JyB9LAogIHRpdGxlOiAgICB7IGNvbG9yOiAnI2I1YjVjMCcsIGZvbnRTaXplOiAnMTZweCcsIGZvbnRXZWlnaHQ6IDcwMCwgbWFyZ2luQm90dG9tOiAnMTBweCcgfSwKICB0YWJsZTogICAgeyB3aWR0aDogJzEwMCUnLCBib3JkZXJDb2xsYXBzZTogJ2NvbGxhcHNlJywgZm9udFNpemU6ICcxM3B4JywgYmFja2dyb3VuZDogJyMxMTEyMTcnLCBib3JkZXJSYWRpdXM6ICc2cHgnLCBvdmVyZmxvdzogJ2hpZGRlbicsIGJvcmRlcjogJzFweCBzb2xpZCAjMjIyJyB9LAogIHRoOiAgICAgICB7IGJhY2tncm91bmQ6ICcjMDAwMDAwJywgY29sb3I6ICcjZjhmOWZhJywgcGFkZGluZzogJzhweCAxMHB4JywgdGV4dEFsaWduOiAnbGVmdCcsIGZvbnRTaXplOiAnMTJweCcsIGZvbnRXZWlnaHQ6IDYwMCwgdGV4dFRyYW5zZm9ybTogJ3VwcGVyY2FzZScsIGxldHRlclNwYWNpbmc6ICcwLjVweCcgfSwKICB0ZDogICAgICAgeyBwYWRkaW5nOiAnOHB4IDEwcHgnLCBib3JkZXJCb3R0b206ICcxcHggc29saWQgIzFjMWQyOScsIGNvbG9yOiAnI2Y4ZjlmYScsIHZlcnRpY2FsQWxpZ246ICdtaWRkbGUnIH0sCiAgdHJFdmVuOiAgIHsgYmFja2dyb3VuZDogJyMxMTEyMTcnIH0sCiAgdHJPZGQ6ICAgIHsgYmFja2dyb3VuZDogJyMxNTE2MjInIH0sCiAgcHRzOiAgICAgIHsgZm9udFdlaWdodDogNzAwLCBjb2xvcjogJyM2NjdlZWEnIH0sCiAgdG9nZ2xlOiAgIHsgYmFja2dyb3VuZDogJ25vbmUnLCBib3JkZXI6ICdub25lJywgY29sb3I6ICcjNjY3ZWVhJywgY3Vyc29yOiAncG9pbnRlcicsIGZvbnRTaXplOiAnMTNweCcsIHBhZGRpbmc6IDAsIHRleHREZWNvcmF0aW9uOiAndW5kZXJsaW5lJyB9LAogIGVtcHR5OiAgICB7IGNvbG9yOiAnIzc3Nzk4YScsIGZvbnRTdHlsZTogJ2l0YWxpYycsIGZvbnRTaXplOiAnMTNweCcsIG1hcmdpblRvcDogJzhweCcgfSwKICBhY2tCYWRnZTogeyBkaXNwbGF5OiAnZmxleCcsIGFsaWduSXRlbXM6ICdjZW50ZXInLCBnYXA6ICc0cHgnLCBmb250U2l6ZTogJzExcHgnLCBjb2xvcjogJyM0Y2FmNTAnIH0sCiAgc2lnbkJ0bjogIHsgYmFja2dyb3VuZDogJ25vbmUnLCBib3JkZXI6ICcxcHggc29saWQgIzIxOTZGMycsIGNvbG9yOiAnIzY0YjVmNicsIGN1cnNvcjogJ3BvaW50ZXInLCBmb250U2l6ZTogJzExcHgnLCBwYWRkaW5nOiAnM3B4IDhweCcsIGJvcmRlclJhZGl1czogJzRweCcsIHdoaXRlU3BhY2U6ICdub3dyYXAnIH0sCiAgc2lnbkZvcm06ICB7IG1hcmdpblRvcDogJzhweCcsIGJhY2tncm91bmQ6ICcjMGQxNjFmJywgYm9yZGVyOiAnMXB4IHNvbGlkICMyMTk2RjMnLCBib3JkZXJSYWRpdXM6ICc2cHgnLCBwYWRkaW5nOiAnMTJweCcsIGRpc3BsYXk6ICdmbGV4JywgZmxleERpcmVjdGlvbjogJ2NvbHVtbicsIGdhcDogJzhweCcgfSwKICBzaWduSW5wdXQ6IHsgcGFkZGluZzogJzZweCAxMHB4JywgYm9yZGVyOiAnMXB4IHNvbGlkICMyYTNhNGEnLCBib3JkZXJSYWRpdXM6ICc0cHgnLCBiYWNrZ3JvdW5kOiAnIzA1MDYwOCcsIGNvbG9yOiAnI2Y4ZjlmYScsIGZvbnRTaXplOiAnMTNweCcsIGZvbnRGYW1pbHk6ICdpbmhlcml0JyB9LAogIHNpZ25Sb3c6ICAgeyBkaXNwbGF5OiAnZmxleCcsIGdhcDogJzhweCcsIGFsaWduSXRlbXM6ICdjZW50ZXInIH0sCiAgc2lnblNhdmU6ICB7IGJhY2tncm91bmQ6ICcjMjE5NkYzJywgY29sb3I6ICd3aGl0ZScsIGJvcmRlcjogJ25vbmUnLCBib3JkZXJSYWRpdXM6ICc0cHgnLCBwYWRkaW5nOiAnNXB4IDEycHgnLCBjdXJzb3I6ICdwb2ludGVyJywgZm9udFNpemU6ICcxM3B4JyB9LAogIHNpZ25DYW5jZWw6IHsgYmFja2dyb3VuZDogJ25vbmUnLCBib3JkZXI6ICcxcHggc29saWQgIzQ0NDQ1NicsIGNvbG9yOiAnIzlhOWNiMicsIGN1cnNvcjogJ3BvaW50ZXInLCBib3JkZXJSYWRpdXM6ICc0cHgnLCBwYWRkaW5nOiAnNXB4IDEycHgnLCBmb250U2l6ZTogJzEzcHgnIH0sCiAgbmVnYXRlZDogICB7IG9wYWNpdHk6IDAuNSwgZm9udFN0eWxlOiAnaXRhbGljJyB9LAp9OwoKZnVuY3Rpb24gZm9ybWF0RGF0ZShkKSB7CiAgaWYgKCFkKSByZXR1cm4gJ+KAkyc7CiAgY29uc3QgZHQgPSBuZXcgRGF0ZShkICsgJ1QxMjowMDowMCcpOwogIHJldHVybiBkdC50b0xvY2FsZURhdGVTdHJpbmcoJ2VuLVVTJywgeyB5ZWFyOiAnbnVtZXJpYycsIG1vbnRoOiAnc2hvcnQnLCBkYXk6ICdudW1lcmljJywgdGltZVpvbmU6ICdBbWVyaWNhL0NoaWNhZ28nIH0pOwp9CgpmdW5jdGlvbiBTaWduQ2VsbCh7IHZpb2xhdGlvbiwgb25TaWduZWQgfSkgewogIGNvbnN0IFtvcGVuLCBzZXRPcGVuXSA9IHVzZVN0YXRlKGZhbHNlKTsKICBjb25zdCBbbmFtZSwgc2V0TmFtZV0gPSB1c2VTdGF0ZSgnJyk7CiAgY29uc3QgW2RhdGUsIHNldERhdGVdID0gdXNlU3RhdGUobmV3IERhdGUoKS50b0lTT1N0cmluZygpLnNsaWNlKDAsIDEwKSk7CiAgY29uc3QgW3NhdmluZywgc2V0U2F2aW5nXSA9IHVzZVN0YXRlKGZhbHNlKTsKICBjb25zdCBbZXJyb3IsIHNldEVycm9yXSA9IHVzZVN0YXRlKG51bGwpOwoKICBpZiAodmlvbGF0aW9uLm5lZ2F0ZWQpIHJldHVybiA8c3BhbiBzdHlsZT17eyBjb2xvcjogJyM1NTU3NjUnIH19PuKAkzwvc3Bhbj47CgogIGlmICh2aW9sYXRpb24uYWNrbm93bGVkZ2VkX2J5KSB7CiAgICByZXR1cm4gKAogICAgICA8ZGl2IHN0eWxlPXtzLmFja0JhZGdlfT4KICAgICAgICA8c3BhbiBzdHlsZT17eyBjb2xvcjogJyM0Y2FmNTAnIH19PuKckyA8L3NwYW4+CiAgICAgICAgPGRpdj4KICAgICAgICAgIDxkaXYgc3R5bGU9e3sgZm9udFdlaWdodDogNjAwLCBjb2xvcjogJyNhNWQ2YTcnIH19PntyaW9sYXRpb24uYWNrbm93bGVkZ2VkX2J5fTwvZGl2PgogICAgICAgICAgPGRpdiBzdHlsZT17eyBjb2xvcjogJyM1NTY2NzEnLCBmb250U2l6ZTogJzExcHgnIH19PntyaW9sYXRpb24uYWNrbm93bGVkZ2VkX2F0ID8gZm9ybWF0RGF0ZSh2aW9sYXRpb24uYWNrbm93bGVkZ2VkX2F0KSA6ICcnfTwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KICAgICk7CiAgfQoKICBjb25zdCBoYW5kbGVTYXZlID0gYXN5bmMgKCkgPT4gewogICAgaWYgKCFuYW1lLnRyaW0oKSkgeyBzZXRFcnJvcignTmFtZSByZXF1aXJlZCcpOyByZXR1cm47IH0KICAgIHNldFNhdmluZyh0cnVlKTsgc2V0RXJyb3IobnVsbCk7CiAgICB0cnkgewogICAgICBhd2FpdCBheGlvcy5wYXRjaChgL2FwaS92aW9sYXRpb25zLyR7dmlvbGF0aW9uLmlkfS9hY2tub3dsZWRnZWAsIHsKICAgICAgICBhY2tub3dsZWRnZWRfYnk6IG5hbWUudHJpbSgpLAogICAgICAgIGFja25vd2xlZGdlZF9hdDogZGF0ZSB8fCBudWxsLAogICAgICB9KTsKICAgICAgb25TaWduZWQodmlvbGF0aW9uLmlkLCBuYW1lLnRyaW0oKSwgZGF0ZSk7CiAgICAgIHNldE9wZW4oZmFsc2UpOwogICAgfSBjYXRjaCAoZSkgewogICAgICBzZXRFcnJvcihlLnJlc3BvbnNlPy5kYXRhPy5lcnJvciB8fCAnRmFpbGVkIHRvIHNhdmUnKTsKICAgIH0gZmluYWxseSB7CiAgICAgIHNldFNhdmluZyhmYWxzZSk7CiAgICB9CiAgfTsKCiAgcmV0dXJuICgKICAgIDxkaXY+CiAgICAgIHshb3BlbiAmJiAoCiAgICAgICAgPGJ1dHRvbiBzdHlsZT17cy5zaWduQnRufSBvbkNsaWNrPXsoKSA9PiBzZXRPcGVuKHRydWUpfT4KICAgICAgICAgIOKck yBTaWduCiAgICAgICAgPC9idXR0b24+CiAgICAgICl9CiAgICAgIHtvcGVuICYmICgKICAgICAgICA8ZGl2IHN0eWxlPXtzLnNpZ25Gb3JtfT4KICAgICAgICAgIDxkaXYgc3R5bGU9e3sgZm9udFNpemU6ICcxMXB4JywgY29sb3I6ICcjNjRiNWY2JywgZm9udFdlaWdodDogNjAwIH19PkFja25vd2xlZGdlIFZpb2xhdGlvbiAje3Zpb2xhdGlvbi5pZH08L2Rpdj4KICAgICAgICAgIDxpbnB1dAogICAgICAgICAgICBzdHlsZT17cy5zaWduSW5wdXR9CiAgICAgICAgICAgIHR5cGU9InRleHQiCiAgICAgICAgICAgIHBsYWNlaG9sZGVyPSJFbXBsb3llZSdzIHByaW50ZWQgbmFtZSIKICAgICAgICAgICAgdmFsdWU9e25hbWV9CiAgICAgICAgICAgIG9uQ2hhbmdlPXtlID0+IHNldE5hbWUoZS50YXJnZXQudmFsdWUpfQogICAgICAgICAgICBhdXRvRm9jdXMKICAgICAgICAgIC8+CiAgICAgICAgICA8aW5wdXQKICAgICAgICAgICAgc3R5bGU9e3Muc2lnbklucHV0fQogICAgICAgICAgICB0eXBlPSJkYXRlIgogICAgICAgICAgICB2YWx1ZT17ZGF0ZX0KICAgICAgICAgICAgb25DaGFuZ2U9e2UgPT4gc2V0RGF0ZShlLnRhcmdldC52YWx1ZSl9CiAgICAgICAgICAvPgogICAgICAgICAge2Vycm9yICYmIDxkaXYgc3R5bGU9e3sgZm9udFNpemU6ICcxMXB4JywgY29sb3I6ICcjZjQ4ZmI0JyB9fT57ZXJyb3J9PC9kaXY+fQogICAgICAgICAgPGRpdiBzdHlsZT17cy5zaWduUm93fT4KICAgICAgICAgICAgPGJ1dHRvbiBzdHlsZT17cy5zaWduU2F2ZX0gb25DbGljaz17aGFuZGxlU2F2ZX0gZGlzYWJsZWQ9e3NhdmluZ30+CiAgICAgICAgICAgICAge3NhdmluZyA/ICdTYXZpbmcuLi4nIDogJ1NhdmUgU2lnbmF0dXJlJ30KICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgIDxidXR0b24gc3R5bGU9e3Muc2lnbkNhbmNlbH0gb25DbGljaz17KCkgPT4geyBzZXRPcGVuKGZhbHNlKTsgc2V0RXJyb3IobnVsbCk7IH19PgogICAgICAgICAgICAgIENhbmNlbAogICAgICAgICAgICA8L2J1dHRvbj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICApfQogICAgPC9kaXY+CiAgKTsKfQoKZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gVmlvbGF0aW9uSGlzdG9yeSh7IGhpc3RvcnkgPSBbXSwgbG9hZGluZywgb25SZWZyZXNoIH0pIHsKICBjb25zdCBbZXhwYW5kZWQsIHNldEV4cGFuZGVkXSA9IHVzZVN0YXRlKGZhbHNlKTsKICBjb25zdCBbbG9jYWxIaXN0b3J5LCBzZXRMb2NhbEhpc3RvcnldID0gdXNlU3RhdGUoaGlzdG9yeSk7CgogIC8vIFN5bmMgd2hlbiBwYXJlbnQgcHJvcCBjaGFuZ2VzCiAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHsgc2V0TG9jYWxIaXN0b3J5KGhpc3RvcnkpOyB9LCBbaGlzdG9yeV0pOwoKICBjb25zdCBoYW5kbGVTaWduZWQgPSAoaWQsIGFja0J5LCBhY2tBdCkgPT4gewogICAgc2V0TG9jYWxIaXN0b3J5KHByZXYgPT4gcHJldi5tYXAodiA9PgogICAgICB2LmlkID09PSBpZCA/IHsgLi4udiwgYWNrbm93bGVkZ2VkX2J5OiBhY2tCeSwgYWNrbm93bGVkZ2VkX2F0OiBhY2tBdCB9IDogdgogICAgKSk7CiAgICBpZiAob25SZWZyZXNoKSBvblJlZnJlc2goKTsKICB9OwoKICBjb25zdCB2aXNpYmxlID0gZXhwYW5kZWQgPyBsb2NhbEhpc3RvcnkgOiBsb2NhbEhpc3Rvcnkuc2xpY2UoMCwgNSk7CgogIGlmIChsb2FkaW5nKSByZXR1cm4gPHAgc3R5bGU9e3MuZW1wdHl9PkxvYWRpbmcgaGlzdG9yeS4uLjwvcD47CiAgaWYgKCFsb2NhbEhpc3RvcnkubGVuZ3RoKSByZXR1cm4gPHAgc3R5bGU9e3MuZW1wdHl9Pk5vIHZpb2xhdGlvbnMgb24gcmVjb3JkIGZvciB0aGlzIGVtcGxveWVlLjwvcD47CgogIHJldHVybiAoCiAgICA8ZGl2IHN0eWxlPXtzLndyYXBwZXJ9PgogICAgICA8ZGl2IHN0eWxlPXtzLnRpdGxlfT5SZWNlbnQgVmlvbGF0aW9ucyAoe2xvY2FsSGlzdG9yeS5sZW5ndGh9IHRvdGFsKTwvZGl2PgogICAgICA8dGFibGUgc3R5bGU9e3MudGFibGV9PgogICAgICAgIDx0aGVhZD4KICAgICAgICAgIDx0cj4KICAgICAgICAgICAgPHRoIHN0eWxlPXtzLnRofT5EYXRlPC90aD4KICAgICAgICAgICAgPHRoIHN0eWxlPXtzLnRofT5WaW9sYXRpb248L3RoPgogICAgICAgICAgICA8dGggc3R5bGU9e3MudGh9PkNhdGVnb3J5PC90aD4KICAgICAgICAgICAgPHRoIHN0eWxlPXtzLnRofT5QdHM8L3RoPgogICAgICAgICAgICA8dGggc3R5bGU9e3MudGh9PkRldGFpbHM8L3RoPgogICAgICAgICAgICA8dGggc3R5bGU9e3MudGh9PkFja25vd2xlZGdlZDwvdGg+CiAgICAgICAgICA8L3RyPgogICAgICAgIDwvdGhlYWQ+CiAgICAgICAgPHRib2R5PgogICAgICAgICAge3Zpc2libGUubWFwKCh2LCBpKSA9PiAoCiAgICAgICAgICAgIDx0ciBrZXk9e3YuaWR9IHN0eWxlPXt7IC4uLihpICUgMiA9PT0gMCA/IHMudHJFdmVuIDogcy50ck9kZCksIC4uLih2Lm5lZ2F0ZWQgPyBzLm5lZ2F0ZWQgOiB7fSkgfX0+CiAgICAgICAgICAgICAgPHRkIHN0eWxlPXtzLnRkfT57Zm9ybWF0RGF0ZSh2LmluY2lkZW50X2RhdGUpfTwvdGQ+CiAgICAgICAgICAgICAgPHRkIHN0eWxlPXtzLnRkfT4KICAgICAgICAgICAgICAgIHt2LnZpb2xhdGlvbl9uYW1lfQogICAgICAgICAgICAgICAge3YubmVnYXRlZCAmJiA8c3BhbiBzdHlsZT17eyBtYXJnaW5MZWZ0OiAnNnB4JywgZm9udFNpemU6ICcxMXB4JywgY29sb3I6ICcjNzc3OThhJyB9fT4odm9pZGVkKTwvc3Bhbj59CiAgICAgICAgICAgICAgPC90ZD4KICAgICAgICAgICAgICA8dGQgc3R5bGU9e3sgLi4ucy50ZCwgY29sb3I6ICcjYzBjMmQ2JyB9fT57di5jYXRlZ29yeX08L3RkPgogICAgICAgICAgICAgIDx0ZCBzdHlsZT17eyAuLi5zLnRkLCAuLi5zLnB0cyB9fT57di5wb2ludHN9PC90ZD4KICAgICAgICAgICAgICA8dGQgc3R5bGU9e3sgLi4ucy50ZCwgY29sb3I6ICcjYzBjMmQ2JyB9fT57di5kZXRhaWxzIHx8ICfilpAnfTwvdGQ+CiAgICAgICAgICAgICAgPHRkIHN0eWxlPXtzLnRkfT4KICAgICAgICAgICAgICAgIDxTaWduQ2VsbCB2aW9sYXRpb249e3Z9IG9uU2lnbmVkPXtoYW5kbGVTaWduZWR9IC8+CiAgICAgICAgICAgICAgPC90ZD4KICAgICAgICAgICAgPC90cj4KICAgICAgICAgICkpfQogICAgICAgIDwvdGJvZHk+CiAgICAgIDwvdGFibGU+CiAgICAgIHtsb2NhbEhpc3RvcnkubGVuZ3RoID4gNSAmJiAoCiAgICAgICAgPGRpdiBzdHlsZT17eyBtYXJnaW5Ub3A6ICc4cHgnIH19PgogICAgICAgICAgPGJ1dHRvbiBzdHlsZT17cy50b2dnbGV9IG9uQ2xpY2s9eygpID0+IHNldEV4cGFuZGVkKGUgPT4gIWUpfT4KICAgICAgICAgICAge2V4cGFuZGVkID8gJ+KWsiBTaG93IGxlc3MnIDogYOKWvCBTaG93IGFsbCAke2xvY2FsSGlzdG9yeS5sZW5ndGh9IHZpb2xhdGlvbnNgfQogICAgICAgICAgPC9idXR0b24+CiAgICAgICAgPC9kaXY+CiAgICAgICl9CiAgICA8L2Rpdj4KICApOwp9Cg== \ No newline at end of file