Added new modules and updated existing logic
This commit is contained in:
66
dev/ui-ux/Opus 4.6/src/components/grid-cell/grid-cell.css
Normal file
66
dev/ui-ux/Opus 4.6/src/components/grid-cell/grid-cell.css
Normal file
@@ -0,0 +1,66 @@
|
||||
/* grid-cell — individual shift cell */
|
||||
|
||||
.grid-cell-root {
|
||||
width: var(--cell-width);
|
||||
min-width: var(--cell-width);
|
||||
height: 58px;
|
||||
border-right: 1px solid #f1f5f9;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
transition: background 0.1s ease;
|
||||
}
|
||||
.grid-cell-root:hover:not(.cursor-not-allowed) {
|
||||
background-color: #f8fafc;
|
||||
}
|
||||
|
||||
.grid-cell-compact {
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
.grid-cell-shift-badge {
|
||||
font-size: 9px;
|
||||
font-weight: 800;
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
width: 90%;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-bottom: 2px;
|
||||
border: 1px solid rgba(0,0,0,0.06);
|
||||
}
|
||||
|
||||
.grid-cell-locked-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(241, 245, 249, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.grid-cell-tooltip {
|
||||
padding: 10px 12px;
|
||||
max-width: 220px;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
/* Weekend + highlight helpers (applied via dynamic class) */
|
||||
.grid-cell-bg-weekend { background-color: #f1f5f9 !important; }
|
||||
|
||||
.grid-cell-bg-reading-mode {
|
||||
background-color: #fff9c4 !important;
|
||||
}
|
||||
.grid-cell-bg-reading-mode-intersection {
|
||||
background-color: #fff176 !important;
|
||||
}
|
||||
|
||||
.grid-cell-col-hovered {
|
||||
background-color: var(--highlight-bg) !important;
|
||||
z-index: 1;
|
||||
}
|
||||
112
dev/ui-ux/Opus 4.6/src/components/grid-cell/grid-cell.js
Normal file
112
dev/ui-ux/Opus 4.6/src/components/grid-cell/grid-cell.js
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* grid-cell.js
|
||||
* =============
|
||||
* A single shift cell inside an agent row.
|
||||
* Props: agentId, date
|
||||
*/
|
||||
|
||||
import {
|
||||
formatDateForId,
|
||||
isWeekend,
|
||||
weekendsAreWorkingDays,
|
||||
isCompact,
|
||||
crosshairActive,
|
||||
hoveredDateStr,
|
||||
highlightedRowId,
|
||||
highlightedDateStr
|
||||
} from '../../services/planner-state.js';
|
||||
|
||||
import {
|
||||
getAssignment,
|
||||
hasComment,
|
||||
hasNote,
|
||||
getCommentText,
|
||||
getNoteText
|
||||
} from '../../services/data-service.js';
|
||||
|
||||
import { isCellLocked } from '../../services/socket-service.js';
|
||||
|
||||
export default {
|
||||
name: 'GridCell',
|
||||
props: {
|
||||
agentId: { type: Number, required: true },
|
||||
date: { type: Date, required: true }
|
||||
},
|
||||
emits: ['open-assignment'],
|
||||
setup(props, { emit }) {
|
||||
const cellClass = Vue.computed(() => {
|
||||
const agentId = props.agentId;
|
||||
const date = props.date;
|
||||
const isRow = highlightedRowId.value === agentId;
|
||||
const isCol = highlightedDateStr.value === formatDateForId(date);
|
||||
const isHoverCol = crosshairActive.value && hoveredDateStr.value === formatDateForId(date);
|
||||
const isWknd = isWeekend(date) && !weekendsAreWorkingDays.value;
|
||||
const locked = isCellLocked(agentId, date);
|
||||
|
||||
const classes = ['grid-cell-root'];
|
||||
if (isCompact.value) classes.push('grid-cell-compact');
|
||||
if (isWknd) classes.push('grid-cell-bg-weekend');
|
||||
if (isWknd && !weekendsAreWorkingDays.value) classes.push('cursor-not-allowed');
|
||||
else if (locked) classes.push('cursor-not-allowed');
|
||||
else classes.push('cursor-pointer');
|
||||
|
||||
if (isRow && isCol) classes.push('grid-cell-bg-reading-mode-intersection');
|
||||
else if (isRow || isCol) classes.push('grid-cell-bg-reading-mode');
|
||||
|
||||
if (isHoverCol) classes.push('grid-cell-col-hovered');
|
||||
|
||||
return classes.join(' ');
|
||||
});
|
||||
|
||||
const assignment = Vue.computed(() => getAssignment(props.agentId, props.date));
|
||||
const locked = Vue.computed(() => isCellLocked(props.agentId, props.date));
|
||||
const showShift = Vue.computed(() => weekendsAreWorkingDays.value || !isWeekend(props.date));
|
||||
const comment = Vue.computed(() => hasComment(props.agentId, props.date));
|
||||
const note = Vue.computed(() => hasNote(props.agentId, props.date));
|
||||
const commentTxt = Vue.computed(() => getCommentText(props.agentId, props.date));
|
||||
const noteTxt = Vue.computed(() => getNoteText(props.agentId, props.date));
|
||||
|
||||
const onEnter = () => { hoveredDateStr.value = formatDateForId(props.date); };
|
||||
const onLeave = () => { hoveredDateStr.value = null; };
|
||||
const onClick = () => { emit('open-assignment', props.date); };
|
||||
|
||||
return {
|
||||
cellClass, assignment, locked, showShift,
|
||||
comment, note, commentTxt, noteTxt,
|
||||
onEnter, onLeave, onClick
|
||||
};
|
||||
},
|
||||
template: `
|
||||
<div :class="cellClass"
|
||||
@mouseenter="onEnter"
|
||||
@mouseleave="onLeave"
|
||||
@click="onClick">
|
||||
<template v-if="showShift">
|
||||
<div v-if="assignment"
|
||||
class="grid-cell-shift-badge"
|
||||
:class="assignment.badgeClass">{{ assignment.label }}</div>
|
||||
</template>
|
||||
|
||||
<div v-if="locked" class="grid-cell-locked-overlay">
|
||||
<q-icon name="lock" color="blue-grey-3" size="14px">
|
||||
<q-tooltip class="bg-grey-9 text-white shadow-4 q-pa-sm">This cell is currently being edited by another user.</q-tooltip>
|
||||
</q-icon>
|
||||
</div>
|
||||
|
||||
<div class="absolute-bottom-right q-pa-xs row no-wrap" style="gap: 2px">
|
||||
<q-icon v-if="comment" name="chat_bubble" size="8px" color="blue-grey-3" class="cursor-help opacity-60">
|
||||
<q-tooltip class="bg-white text-grey-9 border grid-cell-tooltip" anchor="top middle" self="bottom middle">
|
||||
<div class="text-weight-bold text-caption text-grey-8 q-mb-xs">User Comment</div>
|
||||
<div class="text-caption text-grey-7">{{ commentTxt }}</div>
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon v-if="note" name="info" size="8px" color="orange-4" class="cursor-help opacity-70">
|
||||
<q-tooltip class="bg-white text-grey-9 border grid-cell-tooltip" anchor="top middle" self="bottom middle">
|
||||
<div class="text-weight-bold text-caption text-grey-8 q-mb-xs">Technical Note</div>
|
||||
<div class="text-caption text-grey-7">{{ noteTxt }}</div>
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
Reference in New Issue
Block a user