@things-factory/work-shift 10.1.155 → 10.1.157
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-client/pages/work-shift.d.ts +8 -0
- package/dist-client/pages/work-shift.js +744 -85
- package/dist-client/pages/work-shift.js.map +1 -1
- package/dist-client/shift-coverage.d.ts +2 -0
- package/dist-client/shift-coverage.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/translations/en.json +6 -0
- package/translations/es.json +6 -0
- package/translations/ja.json +6 -0
- package/translations/ko.json +6 -0
- package/translations/ms.json +6 -0
- package/translations/zh.json +6 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-shift.js","sourceRoot":"","sources":["../../client/pages/work-shift.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,EAAE,YAAY,IAAI,CAAC,EAAE,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,4EAA4E,CAAA;AAC9J,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sEAAsE,CAAA;AAG3G,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,QAAQ;IAAhC;;QAiBY,YAAO,GAAG,EAAE,CAAA;QACZ,SAAI,GAAG,KAAK,CAAA;QACZ,aAAQ,GAAwB,EAAE,CAAA;QAC3C,UAAK,GAAG,KAAK,CAAA;IA8HvB,CAAC;aAjJQ,WAAM,GAAG,CAAC,kBAAkB,EAAE,eAAe,EAAE,cAAc,EAAE,GAAG,CAAA;;;;;;;;;;;;;GAaxE,CAAC,AAbW,CAaX;IAOF,IAAI,OAAO,KAAU,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAA,CAAC,CAAC;IAClH,KAAK,CAAC,WAAW,KAAK,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA,CAAC,CAAC;IACjE,OAAO;QACb,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAA;QAC/E,OAAO,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;IACzF,CAAC;IACO,KAAK,CAAC,GAAG,CAAC,MAA2B;QAC3C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;QACnC,IAAI,CAAC;YAAC,MAAM,MAAM,EAAE,CAAA;QAAC,CAAC;QAAC,OAAM,CAAM,EAAE,CAAC;YAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAA;QAAC,CAAC;gBACzD,CAAC;YAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAA;QAAC,CAAC;IAC/B,CAAC;IACO,KAAK,CAAC,IAAI;QAChB,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE;YACxB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAA,qCAAqC,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAA;YAC/G,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;YACpE,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAA;YACrD,MAAM,QAAQ,GAAwB,EAAE,CAAA;YACxC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBACnF,IAAI,OAAiC,CAAA;gBACrC,QAAQ,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,sBAAsB,EAAE,EAAE,MAAM,EAAE,EAAE,kBAAkB,EAAE,GAAG,CAAC,kBAAkB,EAAE,WAAW,EAAE,CAAC,CAAe,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;gBAC1K,IAAI,OAAO;oBAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,OAAO,CAAA;YAC/C,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QAC1B,CAAC,CAAC,CAAA;IACJ,CAAC;IACO,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE;QAChC,IAAI,CAAC,KAAK,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,WAAW,IAAI,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ;YACnG,0DAA0D;YAC1D,MAAM,EAAE,eAAe,CAAC,GAAG,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM;gBACxE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY;gBAC5B,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAChG,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;QACvD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;IACO,MAAM,CAAC,KAAa,EAAE,KAAU,IAAI,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA,CAAC,CAAC;IACvG,WAAW,CAAC,KAAa,EAAE,KAAa,EAAE,KAAU;QAC1D,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACjH,CAAC;IACO,KAAK,CAAC,IAAI;QAChB,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE;YACxB,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;YAC3E,MAAM,OAAO,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,CAAA;YACxE,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAA;YAC/B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO;oBACtD,CAAC,CAAC,GAAG,CAAA,iKAAiK;oBACtK,CAAC,CAAC,GAAG,CAAA,oEAAoE;gBACzE,SAAS,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;YACzH,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;YACxE,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAA;YACnF,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QACpB,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;IACtC,CAAC;IACO,KAAK,CAAC,MAAM;QAClB,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE;YACxB,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC;gBACnC,IAAI,OAAiC,CAAA;gBACrC,QAAQ,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,wBAAwB,EAAE,EAAE,MAAM,EAAE;wBACzE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc;wBACvF,WAAW,EAAE,CAAC,CAAe,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC;qBAAE,EAAE,CAAC,CAAC,CAAA;gBACrD,IAAI,CAAC,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAA;gBACxD,MAAM,OAAO,CAAA;YACf,CAAC;iBAAM,CAAC;gBACN,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;gBAC3E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAA,oKAAoK;oBACpN,SAAS,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc;wBAC/E,OAAO,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;gBAC1E,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM;oBAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;YACtE,CAAC;YACD,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;YAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAC5C,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;IACtC,CAAC;IACO,SAAS,CAAC,GAAQ;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,GAAG,CAAC,EAAE,CAAC,CAAA;QAChF,OAAO,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IAC/F,CAAC;IACO,QAAQ,CAAC,GAAQ,EAAE,KAAa;QACtC,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,CAAC,CAAA;QACvF,OAAO,IAAI,CAAA,qBAAqB,CAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAA,0CAA0C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAC7H,CAAC,CAAM,EAAE,EAAE;YACnB,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAA;YAC3E,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBAAC,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;gBAAC,OAAM;YAAC,CAAC;YACrD,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;QACrG,CAAC,MAAM,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAA;IACjD,CAAC;IACD,MAAM;QACJ,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;QAClI,OAAO,IAAI,CAAA;2CAC4B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC;4BAClF,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,eAAe,CAAC;QAClH,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,mBAAmB,IAAI,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE;qCAChC,CAAC,CAAC,SAAS,CAAC;UACvC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,MAAM,CAAC,CAAC,gBAAgB,EAAC,EAAC,CAAC,EAAC,OAAO,CAAC,cAAc,EAAC,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAK,EAAC,EAAE,CAAA,CAAC,CAAC,KAAK,KAAG,SAAS,CAAC,CAAC,SAAS,CAAC,OAAO,gBAAgB,CAAC,OAAO,EAAC,WAAW,CAAC,EAAE;YACvM,CAAC,CAAC,IAAI,CAAA,MAAM,CAAC,CAAC,YAAY,CAAC,MAAM;;QAEnC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA,gBAAgB,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,EAAC,EAAC,CAAC,EAAC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;UACxK,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;8BACjD,CAAC,aAAa,EAAC,UAAU,EAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAA,UAAU,CAAC,CAAC,KAAK,CAAC,qBAAqB,KAAK,WAAW,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAK,EAAC,EAAE,CAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC;mBACjN,CAAC,CAAC,eAAe,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ,kEAAkE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,CAAK,EAAC,EAAE,GAAC,IAAI,CAAC;YAAA,IAAI,CAAC,MAAM,CAAC,eAAe,EAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QAAA,CAAC;QAAC,OAAM,GAAO,EAAC,CAAC;YAAA,IAAI,CAAC,OAAO,GAAC,GAAG,CAAC,OAAO,CAAA;QAAA,CAAC,CAAA,CAAC;;gDAEnR,CAAC,MAAM,EAAC,UAAU,EAAC,UAAU,EAAC,QAAQ,EAAC,QAAQ,EAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA,EAAE,CAAA,IAAI,CAAA,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAChI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAO,EAAC,KAAY,EAAC,EAAE,CAAA,IAAI,CAAA;oCAC1B,OAAO,GAAC,KAAK,WAAW,GAAG,CAAC,IAAI,WAAW,CAAC,CAAK,EAAC,EAAE,CAAA,IAAI,CAAC,WAAW,CAAC,KAAK,EAAC,MAAM,EAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;uBAC9G,CAAC,CAAC,aAAa,CAAC,qBAAqB,cAAc,GAAC,KAAK,WAAW,GAAG,CAAC,WAAW,IAAI,EAAE,WAAW,CAAC,CAAK,EAAC,EAAE,CAAA,IAAI,CAAC,WAAW,CAAC,KAAK,EAAC,aAAa,EAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;cAC1K,CAAC,MAAM,EAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAA,EAAE,CAAA,IAAI,CAAA,0BAA0B,IAAI,GAAC,OAAO,GAAC,KAAK,YAAY,CAAC,CAAK,EAAC,EAAE,CAAA,IAAI,CAAC,WAAW,CAAC,KAAK,EAAC,IAAI,GAAC,MAAM,EAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA,EAAE,CAAA,IAAI,CAAA,iBAAiB,CAAC,cAAc,CAAC,KAAK,GAAG,CAAC,IAAI,GAAC,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,GAAC,CAAC,CAAC,WAAW,CAAC;sCAC/O,IAAI,GAAC,OAAO,GAAC,KAAK,uBAAuB,GAAG,CAAC,IAAI,GAAC,MAAM,CAAC,WAAW,CAAC,CAAK,EAAC,EAAE,CAAA,IAAI,CAAC,WAAW,CAAC,KAAK,EAAC,IAAI,GAAC,MAAM,EAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;kBAC9J,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAC,KAAK,CAAC,8BAA8B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,KAAG,CAAC,WAAW,GAAE,EAAE,CAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAK,EAAC,CAAQ,EAAC,EAAE,CAAA,CAAC,KAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;gBAC7L,CAAC;+CAC8B,GAAE,EAAE,CAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAC,EAAC,IAAI,EAAC,EAAE,EAAC,QAAQ,EAAC,CAAC,EAAC,QAAQ,EAAC,OAAO,EAAC,MAAM,EAAC,CAAC,EAAC,MAAM,EAAC,OAAO,EAAC,UAAU,EAAC,EAAE,EAAC,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC;4BACjK,CAAC,CAAC,cAAc,CAAC;6CACA,IAAI,CAAC,IAAI,WAAW,GAAE,EAAE,CAAA,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,YAAY,CAAC;8CACrD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,WAAW,GAAE,EAAE,CAAA,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,iBAAiB;4BACnO,IAAI,CAAC,IAAI,WAAW,GAAE,EAAE,GAAC,IAAG,CAAC,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAC,CAAC;YAAA,IAAI,CAAC,KAAK,GAAC,SAAS,CAAC;YAAA,IAAI,CAAC,KAAK,GAAC,KAAK,CAAA;QAAA,CAAC,CAAA,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC;UAC/J,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA,4DAA4D,IAAI,WAAW,IAAI,CAAC,KAAK,oCAAoC,CAAC,CAAC,CAAC,EAAE;iBAC3I,CAAC,CAAC,CAAC,EAAE;QACd,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,gBAAgB,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,GAAO,EAAC,EAAE;YAC9G,MAAM,MAAM,GAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAK,EAAC,EAAE,CAAA,CAAC,CAAC,UAAU,KAAG,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,GAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YACtG,OAAO,IAAI,CAAA,sCAAsC,IAAI,CAAC,KAAK,WAAW,GAAE,EAAE,GAAC,IAAI,CAAC,KAAK,GAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAA,IAAI,CAAC,KAAK,GAAC,KAAK,CAAA,CAAA,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAC,EAAC,CAAC,EAAC,GAAG,CAAC,cAAc,EAAC,CAAC,+BAA+B,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;kBACrN,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA,GAAG,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA,GAAG,CAAC,CAAC,eAAe,CAAC,KAAK,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE;YAC/L,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,SAAS,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,kBAAkB,GAAE,EAAE,CAAA,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;8BAC1I,IAAI,CAAC,KAAK,WAAW,GAAE,EAAE,CAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,iBAAiB,CAAA;QACvG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE;WACd,CAAA;IACT,CAAC;;AAlIgB;IAAhB,KAAK,EAAE;;2CAAsB;AACb;IAAhB,KAAK,EAAE;;wCAAmB;AACV;IAAhB,KAAK,EAAE;;0CAAqB;AACZ;IAAhB,KAAK,EAAE;;uCAAqB;AACZ;IAAhB,KAAK,EAAE;;2CAA2C;AAnBxC,SAAS;IADrB,aAAa,CAAC,YAAY,CAAC;GACf,SAAS,CAkJrB","sourcesContent":["import gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\nimport { PageView } from '@operato/shell'\nimport { DocumentPageStyles, ScrollbarStyles } from '@operato/styles'\nimport { revisionText as t, revisionDate, revisionContents, revisionStyles } from '@things-factory/ops-master/dist-client/pages/master/revision-comparison.js'\nimport { localDateTime, isoFromLocal } from '@things-factory/ops-master/dist-client/pages/master/revision-view.js'\n\n@customElement('work-shift')\nexport class WorkShift extends PageView {\n static styles = [DocumentPageStyles, ScrollbarStyles, revisionStyles, css`\n .page { padding: 20px; display: grid; gap: 20px; min-width: 0; }\n section { border: 1px solid var(--ui-line); border-radius: 6px; padding: 16px; min-width: 0; }\n h2 { font-size: 18px; margin: 0 0 12px; }\n .bar, .fields { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }\n .fields label { display: grid; gap: 5px; flex: 1 1 200px; }\n input, select, textarea { font: inherit; padding: 6px 8px; border: 1px solid var(--ui-line); border-radius: 4px; background: var(--md-sys-color-surface); color: inherit; box-sizing: border-box; max-width: 100%; }\n input[type=time] { width: 105px; }\n .scroll table { min-width: 780px; }\n .week { display:flex; flex-wrap:wrap; gap:4px; max-width:210px; }\n .week label { white-space:nowrap; }\n .current { border-left: 4px solid var(--md-sys-color-primary); }\n .notice { padding:12px; background:var(--md-sys-color-surface-container); }\n `]\n @state() private overview: any\n @state() private draft: any\n @state() private message = ''\n @state() private busy = false\n @state() private statuses: Record<string, any> = {}\n private dirty = false\n get context(): any { return { title: i18next.t('title.work-shift'), frame: 'document', help: 'page/work-shift' } }\n async pageUpdated() { if (this.active && !this.dirty) await this.load() }\n private current() {\n const segment = this.overview?.schedule.find((s: any) => s.state === 'current')\n return segment && this.overview.revisions.find((r: any) => r.id === segment.revisionId)\n }\n private async run(action: () => Promise<void>) {\n this.busy = true; this.message = ''\n try { await action() } catch(e: any) { this.message = e.message }\n finally { this.busy = false }\n }\n private async load() {\n await this.run(async () => {\n const result = await client.query({ query: gql`query { workShiftRevisionOverview }`, fetchPolicy: 'no-cache' })\n if (result.errors?.length) throw new Error(result.errors[0].message)\n this.overview = result.data.workShiftRevisionOverview\n const statuses: Record<string, any> = {}\n for (const row of this.overview.revisions.filter((r: any) => r.activityInstanceId)) {\n let promise: Promise<any> | undefined\n document.dispatchEvent(new CustomEvent('master-change-status', { detail: { activityInstanceId: row.activityInstanceId, respondWith: (p: Promise<any>) => promise = p } }))\n if (promise) statuses[row.id] = await promise\n }\n this.statuses = statuses\n })\n }\n private begin(row = this.current()) {\n this.draft = { description: row?.description ?? '', timezone: row?.timezone ?? this.overview.timezone,\n /* 편성이 아직 없으면 옛 교대로 시작한다 — 운영자가 그것을 보고 고친다(2026-09-24). */\n shifts: structuredClone(row?.shifts ?? (this.overview.legacyShifts?.length\n ? this.overview.legacyShifts\n : [{ name: '', fromDate: 0, fromTime: '08:00', toDate: 0, toTime: '16:00', daysOfWeek: '' }])),\n effectiveFrom: new Date().toISOString(), reason: '' }\n this.dirty = false\n }\n private change(field: string, value: any) { this.draft = { ...this.draft, [field]: value }; this.dirty = true }\n private changeShift(index: number, field: string, value: any) {\n this.change('shifts', this.draft.shifts.map((s: any, i: number) => i === index ? { ...s, [field]: value } : s))\n }\n private async save() {\n await this.run(async () => {\n const { description, timezone, shifts, effectiveFrom, reason } = this.draft\n const content = { description, timezone, shifts, effectiveFrom, reason }\n const editing = !!this.draft.id\n const response = await client.mutate({ mutation: editing\n ? gql`mutation($revisionId:String!,$editGeneration:Int!,$content:Object!){editWorkShiftDraft(revisionId:$revisionId,editGeneration:$editGeneration,content:$content)}`\n : gql`mutation($content:Object!){createWorkShiftDraft(content:$content)}`,\n variables: { content, ...(editing ? { revisionId: this.draft.id, editGeneration: this.draft.editGeneration } : {}) } })\n if (response.errors?.length) throw new Error(response.errors[0].message)\n this.draft = response.data[editing ? 'editWorkShiftDraft' : 'createWorkShiftDraft']\n this.dirty = false\n })\n if (!this.message) await this.load()\n }\n private async submit() {\n await this.run(async () => {\n if (this.overview.approvalRequired) {\n let promise: Promise<any> | undefined\n document.dispatchEvent(new CustomEvent('master-change-approval', { detail: {\n axis: 'workShift', revisionId: this.draft.id, editGeneration: this.draft.editGeneration,\n respondWith: (p: Promise<any>) => promise = p } }))\n if (!promise) throw new Error(t('approval-unavailable'))\n await promise\n } else {\n const { description, timezone, shifts, effectiveFrom, reason } = this.draft\n const result = await client.mutate({ mutation: gql`mutation($revisionId:String,$editGeneration:Int,$content:Object!){saveAndPublishWorkShift(revisionId:$revisionId,editGeneration:$editGeneration,content:$content)}`,\n variables: { revisionId: this.draft.id, editGeneration: this.draft.editGeneration,\n content: { description, timezone, shifts, effectiveFrom, reason } } })\n if (result.errors?.length) throw new Error(result.errors[0].message)\n }\n this.draft = undefined; this.dirty = false\n })\n if (!this.message) await this.load()\n }\n private rowStatus(row: any) {\n const segment = this.overview.schedule.find((s: any) => s.revisionId === row.id)\n return segment?.state ?? this.statuses[row.id]?.state ?? (row.frozenAt ? 'pending' : 'draft')\n }\n private weekdays(row: any, index: number) {\n const days = row.daysOfWeek ? row.daysOfWeek.split(',') : ['0','1','2','3','4','5','6']\n return html`<div class=\"week\">${['1','2','3','4','5','6','0'].map(day => html`<label><input type=\"checkbox\" .checked=${days.includes(day)}\n @change=${(e: any) => {\n const next = e.target.checked ? [...days,day] : days.filter(d => d !== day)\n if (!next.length) { e.target.checked = true; return }\n this.changeShift(index, 'daysOfWeek', next.length === 7 ? '' : [...new Set(next)].sort().join(','))\n }} />${t('weekday-' + day)}</label>`)}</div>`\n }\n render() {\n const current = this.current(), base = this.draft && this.overview?.revisions.find((r: any) => r.id === this.draft.baseRevisionId)\n return html`<div class=\"page\">\n <div class=\"bar\"><button ?disabled=${this.busy || this.dirty} @click=${() => this.load()}>${t('refresh')}</button>\n <button ?disabled=${this.busy || !this.overview || !!this.draft} @click=${() => this.begin()}>${t('create-change')}</button></div>\n ${this.message ? html`<p role=\"alert\">${this.message}</p>` : ''}\n <section class=\"current\"><h2>${t('current')}</h2>\n ${current ? html`<p>${t('revision-value',{n:current.revisionNumber})} · ${revisionDate(this.overview.schedule.find((s:any)=>s.state==='current').validFrom)}</p>${revisionContents(current,'workShift')}`\n : html`<p>${t('no-current')}</p>`}\n </section>\n ${this.draft ? html`<section><h2>${this.draft.id ? t('revision-value',{n:this.draft.revisionNumber}) : t('new')} · ${t(this.draft.id ? this.rowStatus(this.draft) : 'draft')}</h2>\n ${this.draft.frozenAt ? revisionContents(this.draft,'workShift') : html`\n <div class=\"fields\">${['description','timezone','reason'].map(field => html`<label>${t(field)}<input aria-label=${field} .value=${this.draft[field] ?? ''} @input=${(e:any)=>this.change(field,e.target.value)} /></label>`)}\n <label>${t('effectiveFrom')} · ${Intl.DateTimeFormat().resolvedOptions().timeZone}<input aria-label=\"effectiveFrom\" type=\"datetime-local\" .value=${localDateTime(this.draft.effectiveFrom)} @change=${(e:any)=>{try {this.change('effectiveFrom',isoFromLocal(e.target.value))} catch(err:any){this.message=err.message}}} /></label>\n </div>\n <div class=\"scroll\"><table><thead><tr>${['name','fromDate','fromTime','toDate','toTime','daysOfWeek'].map(f=>html`<th>${t(f)}</th>`)}<th></th></tr></thead><tbody>\n ${this.draft.shifts.map((row:any,index:number)=>html`<tr>\n <td><input aria-label=${'name-'+index} .value=${row.name} @input=${(e:any)=>this.changeShift(index,'name',e.target.value)} />\n <label>${t('description')}<input aria-label=${'description-'+index} .value=${row.description ?? ''} @input=${(e:any)=>this.changeShift(index,'description',e.target.value)} /></label></td>\n ${['from','to'].map(side=>html`<td><select aria-label=${side+'Date-'+index} @change=${(e:any)=>this.changeShift(index,side+'Date',Number(e.target.value))}>${[-1,0,1].map(d=>html`<option value=${d} .selected=${d === row[side+'Date']}>${t('day-offset-'+d)}</option>`)}</select></td>\n <td><input aria-label=${side+'Time-'+index} type=\"time\" .value=${row[side+'Time']} @input=${(e:any)=>this.changeShift(index,side+'Time',e.target.value)} /></td>`)}\n <td>${this.weekdays(row,index)}</td><td><button ?disabled=${this.draft.shifts.length===1} @click=${()=>this.change('shifts',this.draft.shifts.filter((_:any,i:number)=>i!==index))}>${t('remove')}</button></td>\n </tr>`)}\n </tbody></table></div><button @click=${()=>this.change('shifts',[...this.draft.shifts,{name:'',fromDate:0,fromTime:'16:00',toDate:1,toTime:'00:00',daysOfWeek:''}])}>${t('add-shift')}</button>\n <p class=\"notice\">${t('shift-impact')}</p>\n <div class=\"bar\"><button ?disabled=${this.busy} @click=${()=>this.save()}>${t('save-draft')}</button>\n <button class=\"primary\" ?disabled=${this.busy || (this.overview.approvalRequired && (this.dirty || !this.draft.id))} @click=${()=>this.submit()}>${this.overview.approvalRequired ? t('request-approval') : i18next.t('button.save')}</button></div>`}\n <button ?disabled=${this.busy} @click=${()=>{if(!this.dirty || window.confirm(t('discard-changes'))){this.draft=undefined;this.dirty=false}}}>${t('close-editor')}</button>\n ${this.draft.id ? html`<ops-master-revision-comparison axis=\"workShift\" .before=${base} .after=${this.draft}></ops-master-revision-comparison>` : ''}\n </section>` : ''}\n ${this.overview ? html`<section><h2>${t('history')}</h2>${[...this.overview.revisions].reverse().map((row:any)=>{\n const period=this.overview.schedule.find((s:any)=>s.revisionId===row.id), status=this.statuses[row.id]\n return html`<div class=\"bar\"><button ?disabled=${this.dirty} @click=${()=>{this.draft=structuredClone(row);this.dirty=false}}>${t('revision-value',{n:row.revisionNumber})}</button><span class=\"pill\">${t(this.rowStatus(row))}</span>\n <span>${period ? html`${revisionDate(period.validFrom)} → ${period.validTo ? revisionDate(period.validTo) : t('until-change')}` : html`${t('effectiveFrom')}: ${revisionDate(row.effectiveFrom)}`}</span>\n ${status?.comment ? html`<span>${status.comment}</span>` : ''}${status?.open ? html`<button @click=${()=>status.open()}>${t('approval-detail')}</button>` : ''}\n <button ?disabled=${this.dirty} @click=${()=>this.begin(row)}>${t('create-change')}</button></div>`\n })}</section>` : ''}\n </div>`\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"work-shift.js","sourceRoot":"","sources":["../../client/pages/work-shift.ts"],"names":[],"mappings":"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","sourcesContent":["import gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\nimport { PageView } from '@operato/shell'\nimport { CommonHeaderStyles, DocumentPageStyles, ScrollbarStyles } from '@operato/styles'\nimport {\n revisionText as t,\n revisionDate,\n revisionContents,\n revisionStyles\n} from '@things-factory/ops-master/dist-client/pages/master/revision-comparison.js'\nimport { localDateTime, isoFromLocal } from '@things-factory/ops-master/dist-client/pages/master/revision-view.js'\n\nimport { clockOf, coverageProblems, coveredMinutes, cycleOf, spanOf, ShiftLike } from '../shift-coverage'\n\nconst DAY_MINUTES = 24 * 60\ntype BandVariant = 'current' | 'scheduled' | 'past'\n\n@customElement('work-shift')\nexport class WorkShift extends PageView {\n static styles = [\n DocumentPageStyles,\n ScrollbarStyles,\n CommonHeaderStyles,\n revisionStyles,\n css`\n .page {\n display: grid;\n gap: var(--spacing-large);\n min-width: 0;\n }\n .page-actions,\n .action-row,\n .history-head {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--spacing-small);\n }\n .page-actions {\n justify-content: space-between;\n }\n .page-section {\n min-width: 0;\n }\n .page-section-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-medium);\n }\n .page-section-header h2,\n .page-section-header h3 {\n margin: 0;\n }\n .current-section {\n border-inline-start: 3px solid var(--ui-accent);\n }\n .editing {\n display: grid;\n gap: var(--spacing-medium);\n padding: var(--spacing-medium);\n border: 1px solid color-mix(in srgb, var(--ui-accent) 35%, transparent);\n border-radius: var(--ui-r-small, 6px);\n background: color-mix(in srgb, var(--ui-accent) 7%, var(--ui-bg));\n }\n .field-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));\n gap: var(--spacing-medium);\n }\n .field {\n display: grid;\n align-content: start;\n gap: var(--spacing-small);\n min-width: 0;\n }\n .field > span,\n .field-label {\n display: block;\n color: var(--ui-muted);\n font-size: var(--ui-t-small);\n }\n input,\n select,\n textarea {\n box-sizing: border-box;\n width: 100%;\n min-height: var(--form-element-height-medium, 40px);\n padding: 7px 10px;\n border: 1px solid var(--ui-line);\n border-radius: var(--ui-r-small, 6px);\n background: var(--ui-panel);\n color: var(--ui-ink);\n font: inherit;\n }\n input[type='time'] {\n font-variant-numeric: tabular-nums;\n }\n .shift-list {\n display: grid;\n gap: var(--spacing-small);\n }\n .shift-card {\n min-width: 0;\n padding: var(--spacing-medium);\n border: 1px solid var(--ui-line);\n border-radius: var(--ui-r-small, 6px);\n background: var(--ui-panel);\n }\n .shift-card-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-small);\n margin-bottom: var(--spacing-medium);\n }\n .shift-card-head strong {\n font-size: var(--ui-t-title);\n }\n .shift-fields {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: var(--spacing-medium);\n }\n .period {\n display: grid;\n grid-template-columns: minmax(88px, 0.8fr) minmax(110px, 1fr);\n align-items: end;\n gap: var(--spacing-small);\n }\n .weekdays {\n margin: var(--spacing-medium) 0 0;\n padding: var(--spacing-small) var(--spacing-medium) var(--spacing-medium);\n border: 1px solid var(--ui-line);\n border-radius: var(--ui-r-small, 6px);\n }\n .weekdays legend {\n padding: 0 var(--spacing-tiny);\n color: var(--ui-muted);\n font-size: var(--ui-t-small);\n }\n .week-options {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-small) var(--spacing-medium);\n }\n .week-options label {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-small);\n white-space: nowrap;\n }\n .week-options input {\n width: 18px;\n min-height: 18px;\n margin: 0;\n accent-color: var(--ui-accent);\n }\n .every-day {\n margin-top: var(--spacing-small);\n }\n .shift-coverage {\n display: grid;\n gap: var(--spacing-small);\n }\n .coverage-title {\n margin: 0;\n font-size: var(--ui-t-title);\n }\n .coverage-groups {\n display: grid;\n gap: var(--spacing-medium);\n }\n .history-bands,\n .history-band-group {\n display: grid;\n gap: var(--spacing-small);\n }\n .coverage-group {\n display: grid;\n gap: var(--spacing-small);\n min-width: 0;\n padding: var(--spacing-medium);\n border: 1px solid var(--ui-line);\n border-radius: var(--ui-r-small, 6px);\n background: var(--ui-panel);\n }\n .coverage-group h4 {\n margin: 0;\n font-size: var(--ui-t-body);\n }\n .band {\n position: relative;\n height: 48px;\n overflow: hidden;\n border: 1px solid var(--ui-line);\n border-radius: var(--ui-r-small, 6px);\n background: repeating-linear-gradient(45deg, var(--ui-panel) 0 5px, var(--ui-line) 5px 6px);\n }\n .band[data-variant='scheduled'] {\n height: 40px;\n }\n .band[data-variant='past'] {\n height: 32px;\n }\n .piece {\n position: absolute;\n inset-block: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n padding-inline: 3px;\n border-inline: 1px solid var(--ui-panel);\n background: var(--ui-accent);\n color: var(--ui-on-accent);\n font-size: var(--ui-t-small);\n line-height: 1.2;\n text-align: center;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .piece-label {\n display: block;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .piece[data-overlap] {\n background: repeating-linear-gradient(\n -45deg,\n var(--ui-warn) 0 5px,\n color-mix(in srgb, var(--ui-warn) 72%, var(--ui-ink)) 5px 7px\n );\n }\n .band[data-variant='scheduled'] .piece {\n border: 1px dashed var(--ui-accent);\n background: color-mix(in srgb, var(--ui-accent) 28%, var(--ui-panel));\n color: var(--ui-ink);\n }\n .band[data-variant='past'] .piece {\n background: color-mix(in srgb, var(--ui-muted) 35%, var(--ui-panel));\n color: var(--ui-ink);\n }\n .ticks {\n display: flex;\n justify-content: space-between;\n gap: var(--spacing-small);\n color: var(--ui-muted);\n font: var(--ui-t-micro) var(--ui-mono);\n }\n .finding,\n .settled,\n .notice,\n .empty {\n padding: var(--spacing-small) var(--spacing-medium);\n border-inline-start: 3px solid var(--ui-warn);\n background: var(--ui-panel);\n line-height: 1.6;\n }\n .settled {\n border-color: var(--ui-good);\n color: var(--ui-muted);\n }\n .notice {\n border-color: var(--ui-info);\n }\n .guidance {\n margin: 0;\n padding-inline-start: 1.25rem;\n color: var(--ui-muted);\n line-height: 1.6;\n }\n .guidance li + li {\n margin-top: var(--spacing-small);\n }\n .empty {\n border-color: var(--ui-line);\n color: var(--ui-muted);\n }\n .history-list {\n display: grid;\n gap: var(--spacing-medium);\n }\n .history-item {\n display: grid;\n gap: var(--spacing-small);\n min-width: 0;\n padding-block: var(--spacing-small);\n border-bottom: 1px solid var(--ui-line);\n }\n .history-head {\n justify-content: flex-start;\n }\n .history-period {\n color: var(--ui-muted);\n font-variant-numeric: tabular-nums;\n }\n .history-actions {\n display: flex;\n align-items: center;\n gap: var(--spacing-small);\n margin-inline-start: auto;\n }\n .status {\n display: inline-flex;\n align-items: center;\n min-height: 26px;\n padding: 2px 9px;\n border-radius: 999px;\n background: var(--ui-accent-wash);\n color: var(--ui-ink);\n }\n .status[data-state='current'],\n .status[data-state='approved'] {\n background: color-mix(in srgb, var(--ui-good) 16%, var(--ui-panel));\n }\n .status[data-state='pending'],\n .status[data-state='scheduled'] {\n background: color-mix(in srgb, var(--ui-info) 16%, var(--ui-panel));\n }\n .status[data-state='rejected'] {\n background: color-mix(in srgb, var(--ui-warn) 18%, var(--ui-panel));\n }\n .history-detail {\n margin-top: var(--spacing-small);\n }\n button {\n min-height: var(--form-action-height, 40px);\n border-radius: var(--ui-r-small, 6px);\n }\n button:focus-visible,\n input:focus-visible,\n select:focus-visible,\n summary:focus-visible {\n outline-color: var(--ui-accent);\n }\n @media (max-width: 640px) {\n .shift-fields {\n grid-template-columns: minmax(0, 1fr);\n }\n .period {\n grid-template-columns: minmax(82px, 0.8fr) minmax(0, 1fr);\n }\n .history-actions {\n width: 100%;\n margin-inline-start: 0;\n }\n .history-actions button {\n flex: 1;\n }\n .piece {\n font-size: var(--ui-t-micro);\n }\n }\n `\n ]\n\n @state() private overview: any\n @state() private draft: any\n @state() private message = ''\n @state() private busy = false\n @state() private statuses: Record<string, any> = {}\n private dirty = false\n\n get context(): any {\n return { title: i18next.t('title.work-shift'), frame: 'document', help: 'page/work-shift' }\n }\n async pageUpdated() {\n if (this.active && !this.dirty) await this.load()\n }\n\n private current() {\n const segment = this.overview?.schedule.find((s: any) => s.state === 'current')\n return segment && this.overview.revisions.find((r: any) => r.id === segment.revisionId)\n }\n\n private async run(action: () => Promise<void>) {\n this.busy = true\n this.message = ''\n try {\n await action()\n } catch (e: any) {\n this.message = e.message\n } finally {\n this.busy = false\n }\n }\n\n private async load() {\n await this.run(async () => {\n const result = await client.query({\n query: gql`\n query {\n workShiftRevisionOverview\n }\n `,\n fetchPolicy: 'no-cache'\n })\n if (result.errors?.length) throw new Error(result.errors[0].message)\n this.overview = result.data.workShiftRevisionOverview\n const statuses: Record<string, any> = {}\n for (const row of this.overview.revisions.filter((r: any) => r.activityInstanceId)) {\n let promise: Promise<any> | undefined\n document.dispatchEvent(\n new CustomEvent('master-change-status', {\n detail: { activityInstanceId: row.activityInstanceId, respondWith: (p: Promise<any>) => (promise = p) }\n })\n )\n if (promise) statuses[row.id] = await promise\n }\n this.statuses = statuses\n })\n }\n\n private begin(row = this.current()) {\n this.draft = {\n description: row?.description ?? '',\n timezone: row?.timezone ?? this.overview.timezone,\n shifts: structuredClone(\n row?.shifts ??\n (this.overview.legacyShifts?.length\n ? this.overview.legacyShifts\n : [{ name: '', fromDate: 0, fromTime: '08:00', toDate: 0, toTime: '16:00', daysOfWeek: '' }])\n ),\n effectiveFrom: new Date().toISOString(),\n reason: ''\n }\n this.dirty = false\n }\n\n private change(field: string, value: any) {\n this.draft = { ...this.draft, [field]: value }\n this.dirty = true\n }\n private changeShift(index: number, field: string, value: any) {\n this.change(\n 'shifts',\n this.draft.shifts.map((s: any, i: number) => (i === index ? { ...s, [field]: value } : s))\n )\n }\n\n private async save() {\n await this.run(async () => {\n const { description, timezone, shifts, effectiveFrom, reason } = this.draft\n const content = { description, timezone, shifts, effectiveFrom, reason }\n const editing = !!this.draft.id\n const response = await client.mutate({\n mutation: editing\n ? gql`\n mutation ($revisionId: String!, $editGeneration: Int!, $content: Object!) {\n editWorkShiftDraft(revisionId: $revisionId, editGeneration: $editGeneration, content: $content)\n }\n `\n : gql`\n mutation ($content: Object!) {\n createWorkShiftDraft(content: $content)\n }\n `,\n variables: {\n content,\n ...(editing ? { revisionId: this.draft.id, editGeneration: this.draft.editGeneration } : {})\n }\n })\n if (response.errors?.length) throw new Error(response.errors[0].message)\n this.draft = response.data[editing ? 'editWorkShiftDraft' : 'createWorkShiftDraft']\n this.dirty = false\n })\n if (!this.message) await this.load()\n }\n\n private async submit() {\n await this.run(async () => {\n if (this.overview.approvalRequired) {\n let promise: Promise<any> | undefined\n document.dispatchEvent(\n new CustomEvent('master-change-approval', {\n detail: {\n axis: 'workShift',\n revisionId: this.draft.id,\n editGeneration: this.draft.editGeneration,\n respondWith: (p: Promise<any>) => (promise = p)\n }\n })\n )\n if (!promise) throw new Error(t('approval-unavailable'))\n await promise\n } else {\n const { description, timezone, shifts, effectiveFrom, reason } = this.draft\n const result = await client.mutate({\n mutation: gql`\n mutation ($revisionId: String, $editGeneration: Int, $content: Object!) {\n saveAndPublishWorkShift(revisionId: $revisionId, editGeneration: $editGeneration, content: $content)\n }\n `,\n variables: {\n revisionId: this.draft.id,\n editGeneration: this.draft.editGeneration,\n content: { description, timezone, shifts, effectiveFrom, reason }\n }\n })\n if (result.errors?.length) throw new Error(result.errors[0].message)\n }\n this.draft = undefined\n this.dirty = false\n })\n if (!this.message) await this.load()\n }\n\n private rowStatus(row: any) {\n const segment = this.overview.schedule.find((s: any) => s.revisionId === row.id)\n return segment?.state ?? this.statuses[row.id]?.state ?? (row.frozenAt ? 'pending' : 'draft')\n }\n\n private weekdays(row: any, index: number) {\n const days = row.daysOfWeek ? row.daysOfWeek.split(',') : ['0', '1', '2', '3', '4', '5', '6']\n return html`<fieldset class=\"weekdays\">\n <legend>${t('daysOfWeek')}</legend>\n <div class=\"week-options\">\n ${['1', '2', '3', '4', '5', '6', '0'].map(\n day =>\n html`<label\n ><input\n type=\"checkbox\"\n ?disabled=${this.busy}\n .checked=${days.includes(day)}\n @change=${(e: any) => {\n const next = e.target.checked ? [...days, day] : days.filter((d: string) => d !== day)\n if (!next.length) {\n e.target.checked = true\n return\n }\n this.changeShift(index, 'daysOfWeek', next.length === 7 ? '' : [...new Set(next)].sort().join(','))\n }}\n />${t('weekday-' + day)}</label\n >`\n )}\n </div>\n <button\n class=\"every-day\"\n ?disabled=${this.busy || days.length === 7}\n @click=${() => this.changeShift(index, 'daysOfWeek', '')}\n >\n ${t('every-day')}\n </button>\n <small class=\"field-label\">${i18next.t('text.weekday-workdate-note')}</small>\n </fieldset>`\n }\n\n private timeLabel(minute: number) {\n const time = clockOf(minute)\n return minute >= DAY_MINUTES ? i18next.t('text.next-day-time', { time: clockOf(minute - DAY_MINUTES) }) : time\n }\n\n private band(shifts: ShiftLike[], variant: BandVariant) {\n const cycle = cycleOf(shifts)\n if (!cycle) return ''\n const overlaps = new Set(\n coverageProblems(shifts)\n .filter(problem => problem.kind === 'overlap')\n .flatMap(problem => problem.names)\n )\n return html`<div>\n <div\n class=\"band\"\n data-variant=${variant}\n role=\"img\"\n aria-label=${shifts.map(shift => `${shift.name}: ${t('day-offset-' + (shift.fromDate ?? 0))} ${shift.fromTime}–${t('day-offset-' + (shift.toDate ?? 0))} ${shift.toTime}`).join(', ')}\n >\n ${shifts.map(shift => {\n const span = spanOf(shift)\n if (!span || span.toMinute <= span.fromMinute) return ''\n const left = Math.max(cycle.startMinute, span.fromMinute)\n const right = Math.min(cycle.endMinute, span.toMinute)\n if (right <= left) return ''\n const label = `${shift.name} ${t('day-offset-' + (shift.fromDate ?? 0))} ${shift.fromTime}–${t('day-offset-' + (shift.toDate ?? 0))} ${shift.toTime}`\n return html`<div\n class=\"piece\"\n ?data-overlap=${overlaps.has(shift.name)}\n title=${label}\n style=${`left:${((left - cycle.startMinute) / DAY_MINUTES) * 100}%;width:${((right - left) / DAY_MINUTES) * 100}%`}\n >\n <span class=\"piece-label\">${label}</span>\n </div>`\n })}\n </div>\n <div class=\"ticks\">\n ${[0, 6, 12, 18, 24].map(hour => html`<span>${this.timeLabel(cycle.startMinute + hour * 60)}</span>`)}\n </div>\n </div>`\n }\n\n private problemText(problem: ReturnType<typeof coverageProblems>[number]) {\n const span =\n problem.fromMinute === undefined || problem.toMinute === undefined\n ? ''\n : `${this.timeLabel(problem.fromMinute)}–${this.timeLabel(problem.toMinute)}`\n if (problem.kind === 'gap')\n return i18next.t('text.shift-gap', { span, before: problem.names[0], after: problem.names[1] })\n if (problem.kind === 'overlap')\n return i18next.t('text.shift-overlap', { span, first: problem.names[0], second: problem.names[1] })\n return i18next.t('text.shift-not-a-span', { name: problem.names[0] || '—' })\n }\n\n private weekGroups(shifts: ShiftLike[]) {\n const groups = new Map<string, { days: string[]; shifts: ShiftLike[] }>()\n for (const day of ['1', '2', '3', '4', '5', '6', '0']) {\n const active = shifts.filter(shift => !shift.daysOfWeek || shift.daysOfWeek.split(',').includes(day))\n const key = shifts\n .map((shift, index) => (active.includes(shift) ? String(index) : ''))\n .filter(Boolean)\n .join(',')\n const group = groups.get(key) ?? { days: [], shifts: active }\n group.days.push(day)\n groups.set(key, group)\n }\n return [...groups.values()]\n }\n\n private weekLabel(days: string[], showEveryDay: boolean) {\n return showEveryDay && days.length === 7 ? t('every-day') : days.map(day => t('weekday-' + day)).join(' · ')\n }\n\n private historyBands(shifts: ShiftLike[], variant: BandVariant) {\n const groups = this.weekGroups(shifts)\n return html`<div class=\"history-bands\">\n ${groups.map(\n group =>\n html`<div class=\"history-band-group\">\n ${groups.length > 1 ? html`<h4>${this.weekLabel(group.days, true)}</h4>` : ''}\n ${group.shifts.length ? this.band(group.shifts, variant) : html`<div class=\"empty\">${i18next.t('text.no-shifts-on-day')}</div>`}\n </div>`\n )}\n </div>`\n }\n\n private coverage(shifts: ShiftLike[], variant: BandVariant) {\n if (!shifts.length) return html`<div class=\"empty\">${i18next.t('text.no-shifts-declared')}</div>`\n const dayGroups = this.weekGroups(shifts)\n return html`<section class=\"shift-coverage\" aria-label=${i18next.t('title.shift-coverage')}>\n <h3 class=\"coverage-title\">${i18next.t('title.shift-coverage')}</h3>\n <div class=\"coverage-groups\">\n ${dayGroups.map(group => {\n const problems = coverageProblems(group.shifts)\n const cycle = cycleOf(group.shifts)\n const covered = coveredMinutes(group.shifts)\n const label = this.weekLabel(group.days, dayGroups.length === 1)\n return html`<div class=\"coverage-group\">\n ${dayGroups.length > 1 ? html`<h4>${label}</h4>` : ''}\n ${\n group.shifts.length\n ? html`\n ${cycle ? this.band(group.shifts, variant) : ''}\n ${covered < DAY_MINUTES ? html`<div class=\"finding\">${i18next.t('text.shift-covers-less-than-a-day', { hours: Math.round(covered / 6) / 10 })}</div>` : ''}\n ${problems.map(problem => html`<div class=\"finding\" role=\"status\">${this.problemText(problem)}</div>`)}\n ${!problems.length && covered >= DAY_MINUTES ? html`<div class=\"settled\">${i18next.t('text.shift-covers-the-whole-day')}</div>` : ''}\n `\n : html`<div class=\"empty\">${i18next.t('text.no-shifts-on-day')}</div>`\n }\n </div>`\n })}\n </div>\n </section>`\n }\n\n private shiftEditor(row: any, index: number) {\n const period = (side: 'from' | 'to') =>\n html`<label class=\"field\">\n <span>${t(side === 'from' ? 'fromTime' : 'toTime')}</span>\n <span class=\"period\">\n <select\n ?disabled=${this.busy}\n aria-label=${t(side === 'from' ? 'fromDate' : 'toDate')}\n .value=${String(row[side + 'Date'] ?? 0)}\n @change=${(e: any) => this.changeShift(index, side + 'Date', Number(e.target.value))}\n >\n ${[-1, 0, 1].map(day => html`<option value=${day}>${t('day-offset-' + day)}</option>`)}\n </select>\n <input\n ?disabled=${this.busy}\n aria-label=${t(side === 'from' ? 'fromTime' : 'toTime')}\n type=\"time\"\n .value=${row[side + 'Time'] ?? ''}\n @input=${(e: any) => this.changeShift(index, side + 'Time', e.target.value)}\n />\n </span>\n </label>`\n return html`<article class=\"shift-card\">\n <header class=\"shift-card-head\">\n <strong>${row.name || `${i18next.t('field.shift')} ${index + 1}`}</strong>\n <button\n ?disabled=${this.busy || this.draft.shifts.length === 1}\n aria-label=${`${t('remove')} ${row.name || index + 1}`}\n @click=${() =>\n this.change(\n 'shifts',\n this.draft.shifts.filter((_: any, i: number) => i !== index)\n )}\n >\n ${t('remove')}\n </button>\n </header>\n <div class=\"field-grid\">\n <label class=\"field\"\n ><span>${t('name')}</span\n ><input\n ?disabled=${this.busy}\n .value=${row.name ?? ''}\n @input=${(e: any) => this.changeShift(index, 'name', e.target.value)}\n /></label>\n <label class=\"field\"\n ><span>${t('description')}</span\n ><input\n ?disabled=${this.busy}\n .value=${row.description ?? ''}\n @input=${(e: any) => this.changeShift(index, 'description', e.target.value)}\n /></label>\n </div>\n <div class=\"shift-fields\">${period('from')}${period('to')}</div>\n ${this.weekdays(row, index)}\n </article>`\n }\n\n render() {\n const current = this.current()\n const base = this.draft && this.overview?.revisions.find((r: any) => r.id === this.draft.baseRevisionId)\n return html`<div class=\"page\">\n <div class=\"page-actions\">\n <div class=\"action-row\">\n <button ?disabled=${this.busy || this.dirty} @click=${() => this.load()}>${t('refresh')}</button>\n <button class=\"primary\" ?disabled=${this.busy || !this.overview || !!this.draft} @click=${() => this.begin()}>\n ${t('create-change')}\n </button>\n </div>\n </div>\n ${this.message ? html`<p class=\"finding\" role=\"alert\">${this.message}</p>` : ''}\n ${\n this.overview\n ? html`<section class=\"page-section current-section\">\n <header class=\"page-section-header\">\n <h2>${t('current')}</h2>\n ${current ? html`<span class=\"status\" data-state=\"current\">${t('revision-value', { n: current.revisionNumber })}</span>` : ''}\n </header>\n ${\n current\n ? html`<p class=\"history-period\">\n ${revisionDate(this.overview.schedule.find((s: any) => s.state === 'current').validFrom)}\n </p>\n ${this.coverage(current.shifts ?? [], 'current')}${revisionContents(current, 'workShift')}`\n : html`<div class=\"empty\">${t('no-current')}</div>`\n }\n </section>`\n : ''\n }\n ${\n this.draft\n ? html`<section class=\"page-section\">\n <header class=\"page-section-header\">\n <h2>${this.draft.id ? t('revision-value', { n: this.draft.revisionNumber }) : t('new')}</h2>\n <span class=\"status\" data-state=${this.rowStatus(this.draft)}\n >${t(this.draft.id ? this.rowStatus(this.draft) : 'draft')}</span\n >\n </header>\n ${\n this.draft.frozenAt\n ? html`${this.coverage(this.draft.shifts ?? [], 'scheduled')}${revisionContents(this.draft, 'workShift')}`\n : html`\n <div class=\"editing\">\n <div class=\"field-grid\">\n ${(['description', 'timezone', 'reason'] as const).map(\n field =>\n html`<label class=\"field\"\n ><span>${t(field)}</span>\n <input\n ?disabled=${this.busy}\n aria-label=${t(field)}\n .value=${this.draft[field] ?? ''}\n @input=${(e: any) => this.change(field, e.target.value)}\n /></label>`\n )}\n <label class=\"field\"\n ><span>${t('effectiveFrom')} · ${Intl.DateTimeFormat().resolvedOptions().timeZone}</span>\n <input\n ?disabled=${this.busy}\n aria-label=${t('effectiveFrom')}\n type=\"datetime-local\"\n .value=${localDateTime(this.draft.effectiveFrom)}\n @change=${(e: any) => {\n try {\n this.change('effectiveFrom', isoFromLocal(e.target.value))\n } catch (err: any) {\n this.message = err.message\n }\n }}\n /></label>\n </div>\n <p class=\"field-label\">\n ${i18next.t('text.effective-timezone-note', { timezone: this.draft.timezone, browserTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone })}\n </p>\n <ul class=\"guidance\">\n <li>${i18next.t('text.howto-crossing-midnight')}</li>\n <li>${i18next.t('text.howto-scheduled-applies-itself')}</li>\n </ul>\n <div class=\"shift-list\">\n ${this.draft.shifts.map((row: any, index: number) => this.shiftEditor(row, index))}\n </div>\n <div class=\"action-row\">\n <button\n ?disabled=${this.busy}\n @click=${() => this.change('shifts', [...this.draft.shifts, { name: '', fromDate: 0, fromTime: '16:00', toDate: 1, toTime: '00:00', daysOfWeek: '' }])}\n >\n ${t('add-shift')}\n </button>\n </div>\n ${this.coverage(this.draft.shifts, 'current')}\n <p class=\"notice\">${t('shift-impact')}</p>\n <div class=\"action-row\">\n <button ?disabled=${this.busy} @click=${() => this.save()}>${t('save-draft')}</button>\n <button\n class=\"primary\"\n ?disabled=${this.busy || (this.overview.approvalRequired && (this.dirty || !this.draft.id))}\n @click=${() => this.submit()}\n >\n ${this.overview.approvalRequired ? t('request-approval') : i18next.t('button.save')}\n </button>\n <button\n ?disabled=${this.busy}\n @click=${() => {\n if (!this.dirty || window.confirm(t('discard-changes'))) {\n this.draft = undefined\n this.dirty = false\n }\n }}\n >\n ${t('close-editor')}\n </button>\n </div>\n ${this.overview.approvalRequired && (this.dirty || !this.draft.id) ? html`<p class=\"field-label\">${i18next.t('text.save-before-approval')}</p>` : ''}\n </div>\n `\n }\n ${this.draft.id ? html`<ops-master-revision-comparison axis=\"workShift\" .before=${base} .after=${this.draft}></ops-master-revision-comparison>` : ''}\n </section>`\n : ''\n }\n ${\n this.overview\n ? html`<section class=\"page-section\">\n <header class=\"page-section-header\"><h2>${t('history')}</h2></header>\n ${\n this.overview.revisions.length\n ? html`<div class=\"history-list\">\n ${[...this.overview.revisions].reverse().map((row: any) => {\n const period = this.overview.schedule.find((s: any) => s.revisionId === row.id)\n const status = this.statuses[row.id]\n const state = this.rowStatus(row)\n const variant: BandVariant =\n state === 'current' ? 'current' : state === 'scheduled' ? 'scheduled' : 'past'\n return html`<article class=\"history-item\">\n <div class=\"history-head\">\n <button\n ?disabled=${this.dirty}\n @click=${() => {\n this.draft = structuredClone(row)\n this.dirty = false\n }}\n >\n ${t('revision-value', { n: row.revisionNumber })}\n </button>\n <span class=\"status\" data-state=${state}>${t(state)}</span>\n <span class=\"history-period\"\n >${period ? html`${revisionDate(period.validFrom)} → ${period.validTo ? revisionDate(period.validTo) : t('until-change')}` : html`${t('effectiveFrom')}: ${revisionDate(row.effectiveFrom)}`}</span\n >\n <div class=\"history-actions\">\n ${status?.open ? html`<button ?disabled=${this.busy} @click=${() => status.open()}>${t('approval-detail')}</button>` : ''}\n <button ?disabled=${this.busy || this.dirty} @click=${() => this.begin(row)}>\n ${i18next.t('text.create-change-from-revision')}\n </button>\n </div>\n </div>\n ${row.shifts?.length ? this.historyBands(row.shifts, variant) : ''}\n ${status?.comment ? html`<p>${status.comment}</p>` : ''}\n <details class=\"history-detail\">\n <summary>${i18next.t('text.view-revision-content')}</summary>\n ${revisionContents(row, 'workShift')}\n </details>\n </article>`\n })}\n </div>`\n : html`<div class=\"empty\">${i18next.t('text.no-shift-history')}</div>`\n }\n </section>`\n : ''\n }\n </div>`\n }\n}\n"]}
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
*/
|
|
25
25
|
export interface ShiftLike {
|
|
26
26
|
name: string;
|
|
27
|
+
/** Work weekdays are the operating date of the shift; blank means every day. */
|
|
28
|
+
daysOfWeek?: string;
|
|
27
29
|
/** 시작이 그날인가 전날인가 다음 날인가 — `-1` · `0` · `1`. */
|
|
28
30
|
fromDate: number;
|
|
29
31
|
/** `HH:mm` 또는 `HH:mm:ss`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shift-coverage.js","sourceRoot":"","sources":["../client/shift-coverage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 편성이 하루를 빈틈없이 덮나 — **순수 계산.**\n *\n * ── 왜 이걸 보여야 하나 ────────────────────────────────────────────────────\n * 교대 사이에 틈이 있으면 그 시간에 일어난 일은 **어느 교대에도 속하지 않는다.** 그러면 그 시각을 물은\n * 쪽은 조업일만 받고 교대 이름은 못 받는다. 화면에 편성을 줄로만 보여 주면 그 틈이 안 보인다 —\n * 22:00 에 끝나고 23:00 에 시작하는 것을 사람이 눈으로 세어야 한다.\n *\n * 겹침도 마찬가지다. 두 교대가 겹치면 그 시간의 일이 **먼저 걸린 교대**로 간다. 편성을 적은 사람은\n * 그렇게 되는 줄 모른다.\n *\n * ── 자정이 아니라 첫 교대에서 시작한다 ─────────────────────────────────────\n * 하루를 00:00~24:00 으로 재면 야간 교대가 있는 공장에서 **없는 틈이 보이고 있는 틈이 안 보인다.**\n *\n * ```\n * 주간 08:00-17:00 · 야간 18:00-익일 02:00\n *\n * 00:00 기준 00:00~08:00 이 빈 것으로 보인다 ← 어제 야간이 덮고 있다\n * 02:00~08:00 의 진짜 틈은 안 보인다\n * 첫 교대 기준 17:00~18:00 · 익일 02:00~08:00 ← 둘 다 맞다\n * ```\n *\n * 그래서 **첫 교대가 시작하는 시각부터 24시간**을 한 바퀴로 본다. 그것이 이 공장의 하루다.\n */\n\nexport interface ShiftLike {\n name: string\n /** 시작이 그날인가 전날인가 다음 날인가 — `-1` · `0` · `1`. */\n fromDate: number\n /** `HH:mm` 또는 `HH:mm:ss`. */\n fromTime: string\n toDate: number\n toTime: string\n}\n\nexport interface ShiftSpan {\n name: string\n /** 조업일 시작(0분)부터 몇 분 뒤인가. 전날이면 음수다. */\n fromMinute: number\n toMinute: number\n}\n\nexport interface CoverageProblem {\n kind: 'gap' | 'overlap' | 'not-a-span'\n /** 걸린 교대 이름들. `gap` 은 그 틈의 앞뒤 둘. */\n names: string[]\n fromMinute?: number\n toMinute?: number\n}\n\n/** 이 편성의 한 바퀴 — 첫 교대가 시작하는 시각부터 24시간. */\nexport interface ShiftCycle {\n startMinute: number\n endMinute: number\n spans: ShiftSpan[]\n}\n\nconst DAY = 24 * 60\n\n/** `HH:mm[:ss]` 를 분으로. 읽을 수 없으면 없다고 답한다 — 0 으로 두면 자정으로 읽힌다. */\nexport function minutesOf(time: string): number | undefined {\n const parts = String(time ?? '').split(':')\n\n if (parts.length < 2) {\n return undefined\n }\n\n const hours = Number(parts[0])\n const minutes = Number(parts[1])\n\n if (!Number.isFinite(hours) || !Number.isFinite(minutes)) {\n return undefined\n }\n\n return hours * 60 + minutes\n}\n\n/** 교대 하나를 조업일 기준 분 구간으로. 읽을 수 없으면 없다. */\nexport function spanOf(shift: ShiftLike): ShiftSpan | undefined {\n const from = minutesOf(shift.fromTime)\n const to = minutesOf(shift.toTime)\n\n if (from === undefined || to === undefined) {\n return undefined\n }\n\n return {\n name: shift.name,\n fromMinute: Number(shift.fromDate ?? 0) * DAY + from,\n toMinute: Number(shift.toDate ?? 0) * DAY + to\n }\n}\n\n/**\n * 이 편성의 한 바퀴 — **첫 교대가 시작하는 시각부터 24시간.**\n *\n * 읽을 수 없는 교대는 여기 들지 않는다. 그것은 `coverageProblems` 가 이름과 함께 낸다.\n */\nexport function cycleOf(shifts: ShiftLike[]): ShiftCycle | undefined {\n const spans = shifts\n .map(spanOf)\n .filter((span): span is ShiftSpan => Boolean(span) && span!.toMinute > span!.fromMinute)\n .sort((a, b) => a.fromMinute - b.fromMinute)\n\n if (!spans.length) {\n return undefined\n }\n\n const startMinute = spans[0].fromMinute\n\n return { startMinute, endMinute: startMinute + DAY, spans }\n}\n\n/**\n * 편성을 훑어 틈과 겹침을 찾는다.\n *\n * 빈 편성은 문제가 아니다 — 아직 안 정한 것이지 잘못 정한 것이 아니다. 그 사실은 부르는 쪽이 목록의\n * 길이로 안다.\n *\n * **마지막 교대와 다음 바퀴의 첫 교대 사이도 본다.** 야간 교대가 새벽에 끝나는 공장에서 그 틈이 가장\n * 크고, 자정 기준으로 재면 그것이 보이지 않는다.\n */\nexport function coverageProblems(shifts: ShiftLike[]): CoverageProblem[] {\n const problems: CoverageProblem[] = []\n const spans: ShiftSpan[] = []\n\n for (const shift of shifts) {\n const span = spanOf(shift)\n\n if (!span || span.toMinute <= span.fromMinute) {\n /* 시각을 읽을 수 없거나 구간이 되지 않는다. 빼고 넘어가면 그 교대가 화면에서 사라진다. */\n problems.push({ kind: 'not-a-span', names: [shift.name] })\n continue\n }\n\n spans.push(span)\n }\n\n const sorted = [...spans].sort((a, b) => a.fromMinute - b.fromMinute)\n\n for (let i = 1; i < sorted.length; i += 1) {\n const before = sorted[i - 1]\n const after = sorted[i]\n\n if (after.fromMinute > before.toMinute) {\n problems.push({\n kind: 'gap',\n names: [before.name, after.name],\n fromMinute: before.toMinute,\n toMinute: after.fromMinute\n })\n } else if (after.fromMinute < before.toMinute) {\n problems.push({\n kind: 'overlap',\n names: [before.name, after.name],\n fromMinute: after.fromMinute,\n toMinute: Math.min(before.toMinute, after.toMinute)\n })\n }\n }\n\n /* 한 바퀴가 닫히나 — 마지막 교대가 끝나고 다음 바퀴 첫 교대가 시작할 때까지. */\n if (sorted.length) {\n const first = sorted[0]\n const lastEnd = Math.max(...sorted.map(span => span.toMinute))\n const nextStart = first.fromMinute + DAY\n\n if (lastEnd < nextStart) {\n const last = sorted.find(span => span.toMinute === lastEnd) ?? sorted[sorted.length - 1]\n\n problems.push({ kind: 'gap', names: [last.name, first.name], fromMinute: lastEnd, toMinute: nextStart })\n }\n }\n\n return problems\n}\n\n/** 편성이 덮는 전체 길이(분). 화면이 「24시간을 덮는가」를 말하는 근거. */\nexport function coveredMinutes(shifts: ShiftLike[]): number {\n const spans = shifts.map(spanOf).filter((span): span is ShiftSpan => Boolean(span))\n\n if (!spans.length) {\n return 0\n }\n\n const sorted = [...spans].sort((a, b) => a.fromMinute - b.fromMinute)\n let covered = 0\n let cursorEnd = sorted[0].fromMinute\n\n for (const span of sorted) {\n const start = Math.max(span.fromMinute, cursorEnd)\n\n if (span.toMinute > start) {\n covered += span.toMinute - start\n cursorEnd = span.toMinute\n }\n }\n\n return covered\n}\n\n/** 분을 `HH:mm` 으로. 조업일을 넘어간 것은 넘어간 대로 적는다 — 24:30 은 다음 날 00:30 이다. */\nexport function clockOf(minute: number): string {\n const sign = minute < 0 ? '-' : ''\n const value = Math.abs(minute)\n\n return `${sign}${String(Math.floor(value / 60)).padStart(2, '0')}:${String(value % 60).padStart(2, '0')}`\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shift-coverage.js","sourceRoot":"","sources":["../client/shift-coverage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 편성이 하루를 빈틈없이 덮나 — **순수 계산.**\n *\n * ── 왜 이걸 보여야 하나 ────────────────────────────────────────────────────\n * 교대 사이에 틈이 있으면 그 시간에 일어난 일은 **어느 교대에도 속하지 않는다.** 그러면 그 시각을 물은\n * 쪽은 조업일만 받고 교대 이름은 못 받는다. 화면에 편성을 줄로만 보여 주면 그 틈이 안 보인다 —\n * 22:00 에 끝나고 23:00 에 시작하는 것을 사람이 눈으로 세어야 한다.\n *\n * 겹침도 마찬가지다. 두 교대가 겹치면 그 시간의 일이 **먼저 걸린 교대**로 간다. 편성을 적은 사람은\n * 그렇게 되는 줄 모른다.\n *\n * ── 자정이 아니라 첫 교대에서 시작한다 ─────────────────────────────────────\n * 하루를 00:00~24:00 으로 재면 야간 교대가 있는 공장에서 **없는 틈이 보이고 있는 틈이 안 보인다.**\n *\n * ```\n * 주간 08:00-17:00 · 야간 18:00-익일 02:00\n *\n * 00:00 기준 00:00~08:00 이 빈 것으로 보인다 ← 어제 야간이 덮고 있다\n * 02:00~08:00 의 진짜 틈은 안 보인다\n * 첫 교대 기준 17:00~18:00 · 익일 02:00~08:00 ← 둘 다 맞다\n * ```\n *\n * 그래서 **첫 교대가 시작하는 시각부터 24시간**을 한 바퀴로 본다. 그것이 이 공장의 하루다.\n */\n\nexport interface ShiftLike {\n name: string\n /** Work weekdays are the operating date of the shift; blank means every day. */\n daysOfWeek?: string\n /** 시작이 그날인가 전날인가 다음 날인가 — `-1` · `0` · `1`. */\n fromDate: number\n /** `HH:mm` 또는 `HH:mm:ss`. */\n fromTime: string\n toDate: number\n toTime: string\n}\n\nexport interface ShiftSpan {\n name: string\n /** 조업일 시작(0분)부터 몇 분 뒤인가. 전날이면 음수다. */\n fromMinute: number\n toMinute: number\n}\n\nexport interface CoverageProblem {\n kind: 'gap' | 'overlap' | 'not-a-span'\n /** 걸린 교대 이름들. `gap` 은 그 틈의 앞뒤 둘. */\n names: string[]\n fromMinute?: number\n toMinute?: number\n}\n\n/** 이 편성의 한 바퀴 — 첫 교대가 시작하는 시각부터 24시간. */\nexport interface ShiftCycle {\n startMinute: number\n endMinute: number\n spans: ShiftSpan[]\n}\n\nconst DAY = 24 * 60\n\n/** `HH:mm[:ss]` 를 분으로. 읽을 수 없으면 없다고 답한다 — 0 으로 두면 자정으로 읽힌다. */\nexport function minutesOf(time: string): number | undefined {\n const parts = String(time ?? '').split(':')\n\n if (parts.length < 2) {\n return undefined\n }\n\n const hours = Number(parts[0])\n const minutes = Number(parts[1])\n\n if (!Number.isFinite(hours) || !Number.isFinite(minutes)) {\n return undefined\n }\n\n return hours * 60 + minutes\n}\n\n/** 교대 하나를 조업일 기준 분 구간으로. 읽을 수 없으면 없다. */\nexport function spanOf(shift: ShiftLike): ShiftSpan | undefined {\n const from = minutesOf(shift.fromTime)\n const to = minutesOf(shift.toTime)\n\n if (from === undefined || to === undefined) {\n return undefined\n }\n\n return {\n name: shift.name,\n fromMinute: Number(shift.fromDate ?? 0) * DAY + from,\n toMinute: Number(shift.toDate ?? 0) * DAY + to\n }\n}\n\n/**\n * 이 편성의 한 바퀴 — **첫 교대가 시작하는 시각부터 24시간.**\n *\n * 읽을 수 없는 교대는 여기 들지 않는다. 그것은 `coverageProblems` 가 이름과 함께 낸다.\n */\nexport function cycleOf(shifts: ShiftLike[]): ShiftCycle | undefined {\n const spans = shifts\n .map(spanOf)\n .filter((span): span is ShiftSpan => Boolean(span) && span!.toMinute > span!.fromMinute)\n .sort((a, b) => a.fromMinute - b.fromMinute)\n\n if (!spans.length) {\n return undefined\n }\n\n const startMinute = spans[0].fromMinute\n\n return { startMinute, endMinute: startMinute + DAY, spans }\n}\n\n/**\n * 편성을 훑어 틈과 겹침을 찾는다.\n *\n * 빈 편성은 문제가 아니다 — 아직 안 정한 것이지 잘못 정한 것이 아니다. 그 사실은 부르는 쪽이 목록의\n * 길이로 안다.\n *\n * **마지막 교대와 다음 바퀴의 첫 교대 사이도 본다.** 야간 교대가 새벽에 끝나는 공장에서 그 틈이 가장\n * 크고, 자정 기준으로 재면 그것이 보이지 않는다.\n */\nexport function coverageProblems(shifts: ShiftLike[]): CoverageProblem[] {\n const problems: CoverageProblem[] = []\n const spans: ShiftSpan[] = []\n\n for (const shift of shifts) {\n const span = spanOf(shift)\n\n if (!span || span.toMinute <= span.fromMinute) {\n /* 시각을 읽을 수 없거나 구간이 되지 않는다. 빼고 넘어가면 그 교대가 화면에서 사라진다. */\n problems.push({ kind: 'not-a-span', names: [shift.name] })\n continue\n }\n\n spans.push(span)\n }\n\n const sorted = [...spans].sort((a, b) => a.fromMinute - b.fromMinute)\n\n for (let i = 1; i < sorted.length; i += 1) {\n const before = sorted[i - 1]\n const after = sorted[i]\n\n if (after.fromMinute > before.toMinute) {\n problems.push({\n kind: 'gap',\n names: [before.name, after.name],\n fromMinute: before.toMinute,\n toMinute: after.fromMinute\n })\n } else if (after.fromMinute < before.toMinute) {\n problems.push({\n kind: 'overlap',\n names: [before.name, after.name],\n fromMinute: after.fromMinute,\n toMinute: Math.min(before.toMinute, after.toMinute)\n })\n }\n }\n\n /* 한 바퀴가 닫히나 — 마지막 교대가 끝나고 다음 바퀴 첫 교대가 시작할 때까지. */\n if (sorted.length) {\n const first = sorted[0]\n const lastEnd = Math.max(...sorted.map(span => span.toMinute))\n const nextStart = first.fromMinute + DAY\n\n if (lastEnd < nextStart) {\n const last = sorted.find(span => span.toMinute === lastEnd) ?? sorted[sorted.length - 1]\n\n problems.push({ kind: 'gap', names: [last.name, first.name], fromMinute: lastEnd, toMinute: nextStart })\n }\n }\n\n return problems\n}\n\n/** 편성이 덮는 전체 길이(분). 화면이 「24시간을 덮는가」를 말하는 근거. */\nexport function coveredMinutes(shifts: ShiftLike[]): number {\n const spans = shifts.map(spanOf).filter((span): span is ShiftSpan => Boolean(span))\n\n if (!spans.length) {\n return 0\n }\n\n const sorted = [...spans].sort((a, b) => a.fromMinute - b.fromMinute)\n let covered = 0\n let cursorEnd = sorted[0].fromMinute\n\n for (const span of sorted) {\n const start = Math.max(span.fromMinute, cursorEnd)\n\n if (span.toMinute > start) {\n covered += span.toMinute - start\n cursorEnd = span.toMinute\n }\n }\n\n return covered\n}\n\n/** 분을 `HH:mm` 으로. 조업일을 넘어간 것은 넘어간 대로 적는다 — 24:30 은 다음 날 00:30 이다. */\nexport function clockOf(minute: number): string {\n const sign = minute < 0 ? '-' : ''\n const value = Math.abs(minute)\n\n return `${sign}${String(Math.floor(value / 60)).padStart(2, '0')}:${String(value % 60).padStart(2, '0')}`\n}\n"]}
|