Repository: isucon/isucon11-qualify (language: go)

Issue:
[frontend]グラフを重ねるのをちゃんとする
よく見たら気持ち悪かった
![image](https://user-images.githubusercontent.com/48485650/125062971-ecd02d80-e0e9-11eb-88b4-a2cf1939d02f.png)



Discussion / hints:

Fix patch:
diff --git a/bench/scenario/assets.go b/bench/scenario/assets.go
index ef4325530..80a417799 100644
--- a/bench/scenario/assets.go
+++ b/bench/scenario/assets.go
@@ -4,17 +4,17 @@ package scenario
 var (
 	resourcesHash = map[string]string{ 
 		"/assets/favicon.d0f5f504.svg": "3697a1b6c6d164ec4a5e4db6f7789f05",
-		"/assets/index.8fb7127f.js": "efff7d1ecbbcc21daadcb928ba202c2c",
+		"/assets/index.62e30cf3.js": "d3904e14eefe360216b9cad7d00d9cca",
 		"/assets/index.d5e7f1e4.css": "5d405f55d71bdb985845141637e86326",
 		"/assets/logo_orange.974bf3e6.svg": "10e2dfa0ff27ec4325b781973c646737",
 		"/assets/logo_white.98008342.svg": "f81e35a6821af44ea5b3a77346bcf6ad",
 		"/assets/vendor.f1db1b60.js": "0fba45a67211ef351dd61811cf25cd66",
-		"/index.html": "b989e6fe2a352ad3cf4ff3c42f6aead7",
+		"/index.html": "684b519c758ac54f608d9603a3f84642",
 	}
 	resourcesMap = map[string]string{ 
 		"/assets/favicon.svg": "/assets/favicon.d0f5f504.svg",
 		"/assets/index.css": "/assets/index.d5e7f1e4.css",
-		"/assets/index.js": "/assets/index.8fb7127f.js",
+		"/assets/index.js": "/assets/index.62e30cf3.js",
 		"/assets/logo_orange.svg": "/assets/logo_orange.974bf3e6.svg",
 		"/assets/logo_white.svg": "/assets/logo_white.98008342.svg",
 		"/assets/vendor.js": "/assets/vendor.f1db1b60.js",
diff --git a/webapp/frontend/src/components/IsuGraph/SittingGraph.tsx b/webapp/frontend/src/components/IsuGraph/SittingGraph.tsx
index bca517862..b72b3b8e8 100644
--- a/webapp/frontend/src/components/IsuGraph/SittingGraph.tsx
+++ b/webapp/frontend/src/components/IsuGraph/SittingGraph.tsx
@@ -23,7 +23,9 @@ const SittingGraph = ({ sittingData, timeCategories }: Props) => {
     ],
     xaxis: {
       categories: timeCategories,
-      labels: { show: false }
+      labels: { show: false },
+      axisBorder: { show: false },
+      axisTicks: { show: false }
     },
     plotOptions: {
       heatmap: {
@@ -42,7 +44,7 @@ const SittingGraph = ({ sittingData, timeCategories }: Props) => {
 
   return (
     <div
-      style={{ transform: 'translateX(13px) translateY(-32px) scaleX(0.993)' }}
+      style={{ transform: 'translateX(13px) translateY(-32px) scaleX(1.04)' }}
     >
       <Chart type="heatmap" options={option} series={option.series}></Chart>
     </div>
diff --git a/webapp/frontend/src/components/IsuGraph/TransitionGraph.tsx b/webapp/frontend/src/components/IsuGraph/TransitionGraph.tsx
index 11694e7e6..cb43368a7 100644
--- a/webapp/frontend/src/components/IsuGraph/TransitionGraph.tsx
+++ b/webapp/frontend/src/components/IsuGraph/TransitionGraph.tsx
@@ -32,10 +32,14 @@ const TransitionGraph = ({
       }
     ],
     xaxis: {
-      categories: timeCategories
+      categories: timeCategories,
+      offsetY: 8
     },
     yaxis: {
-      min: 0
+      min: 0,
+      labels: {
+        offsetX: -16
+      }
     },
     tooltip: {
       custom: ({ dataPointIndex }) => {
diff --git a/webapp/public/assets/index.8fb7127f.js b/webapp/public/assets/index.62e30cf3.js
similarity index 68%
rename from webapp/public/assets/index.8fb7127f.js
rename to webapp/public/assets/index.62e30cf3.js
index 7fdd5029c..b5e1f2955 100644
--- a/webapp/public/assets/index.8fb7127f.js
+++ b/webapp/public/assets/index.62e30cf3.js
@@ -1,1 +1,1 @@
-var e=Object.defineProperty,t=Object.defineProperties,a=Object.getOwnPropertyDescriptors,l=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,s=Object.prototype.propertyIsEnumerable,r=(t,a,l)=>a in t?e(t,a,{enumerable:!0,configurable:!0,writable:!0,value:l}):t[a]=l,i=(e,t)=>{for(var a in t||(t={}))n.call(t,a)&&r(e,a,t[a]);if(l)for(var a of l(t))s.call(t,a)&&r(e,a,t[a]);return e},c=(e,l)=>t(e,a(l));import{r as o,R as m,a as u,M as d,L as p,I as E,T as f,b as g,u as x,c as v,d as h,e as y,f as b,g as w,F as N,G as _,_ as C,h as D,i as S,S as j,j as k,B as $,k as I}from"./vendor.f1db1b60.js";const O={me:null},T=o.exports.createContext(O),P=o.exports.createContext(null),q=(e,t)=>{switch(t.type){case"login":return c(i({},e),{me:t.user});case"logout":return c(i({},e),{me:null});default:throw new Error("invalid action")}},z=({children:e})=>{const[t,a]=o.exports.useReducer(q,O);return m.createElement(T.Provider,{value:t},m.createElement(P.Provider,{value:a},e))},U=()=>{const e=o.exports.useContext(T);if(!e)throw new Error("require wrapped by stateContext");return e},G=()=>{const e=o.exports.useContext(P);if(!e)throw new Error("require wrapped by stateContext");return e},L=({children:e})=>m.createElement("div",{className:"text-white-primary font-bold"},e),M=()=>new Date,A=e=>Math.floor(e.getTime()/1e3),F=e=>new Date(1e3*e),V=e=>`${e.getFullYear()}/${B(e.getMonth()+1)}/${B(e.getDate())} ${B(e.getHours())}:${B(e.getMinutes())}:${B(e.getSeconds())}`,B=e=>("0"+e).slice(-2);const R=new class{async postAuth(e,t){await u.post("/api/auth",{},i({headers:{Authorization:`Bearer ${e}`}},t))}async postSignout(e){await u.post("/api/signout",e)}async getUserMe(e){const{data:t}=await u.get("/api/user/me",e);return t}async getIsus(e,t){const{data:a}=await u.get("/api/isu",i({params:e},t)),l=[];for(const n of a)l.push(c(i({},n),{latest_isu_condition:n.latest_isu_condition?c(i({},n.latest_isu_condition),{date:F(n.latest_isu_condition.timestamp)}):null}));return l}async postIsu(e,t){const a=new FormData;a.append("jia_isu_uuid",e.jia_isu_uuid),a.append("isu_name",e.isu_name),e.image&&a.append("image",e.image,e.image.name),await u.post("/api/isu",a,i({headers:{"content-type":"multipart/form-data"}},t))}async getIsu(e,t){const{data:a}=await u.get(`/api/isu/${e}`,t);return a}async deleteIsu(e,t){await u.delete(`/api/isu/${e}`,t)}async getIsuGraphs(e,t,a){const l={datetime:A(t.date)},{data:n}=await u.get(`/api/isu/${e}/graph`,i({params:l},a)),s=[];return n.forEach((e=>{s.push(c(i({},e),{start_at:F(e.start_at),end_at:F(e.end_at)}))})),s}async getIsuConditions(e,t,a){const l=c(i({},t),{start_time:t.start_time?A(t.start_time):void 0,end_time:A(t.end_time)}),{data:n}=await u.get(`/api/condition/${e}`,i({params:l},a)),s=[];return n.forEach((e=>{s.push(c(i({},e),{date:F(e.timestamp)}))})),s}async getTrend(e){const{data:t}=await u.get("/api/trend",i({},e)),a=[];return t.forEach((e=>{const t=[],l=[],n=[];e.info.forEach((e=>{t.push(c(i({},e),{date:F(e.timestamp)}))})),e.warning.forEach((e=>{l.push(c(i({},e),{date:F(e.timestamp)}))})),e.critical.forEach((e=>{n.push(c(i({},e),{date:F(e.timestamp)}))})),a.push(c(i({},e),{info:t,warning:l,critical:n}))})),a}},Z=e=>{const t=G();return m.createElement(d,{isOpen:e.isOpen,onRequestClose:e.toggle,className:"top-18 bg-gray-50 absolute right-0 flex justify-items-center px-6 py-3 border border-outline rounded",overlayClassName:"fixed inset-0",shouldCloseOnOverlayClick:!0},m.createElement(p,{to:"/",onClick:async()=>{await R.postSignout(),t({type:"logout"})},className:"flex items-center text-primary"},m.createElement(E,{className:"mr-1",size:16}),m.createElement("div",null,"logout")))},J=e=>m.createElement(L,null,m.createElement(p,{to:e.to,className:"flex items-center"},e.icon,m.createElement("div",{className:"ml-1"},e.label))),H=()=>{const[e,t]=o.exports.useState(!1),a=()=>{t(!e)},l=U().me;return l?m.createElement("div",{className:"w-52 flex items-center justify-between ml-auto"},m.createElement(J,{to:"/register",label:"ISUの登録",icon:m.createElement(f,null)}),m.createElement("div",{className:"border-l-1 pl-4 border-white"},m.createElement(L,null,m.createElement("div",{className:"flex items-center cursor-pointer",onClick:a},m.createElement(g,null),m.createElement("div",{className:"ml-1"},l.jia_user_id)))),m.createElement(Z,{isOpen:e,toggle:a})):m.createElement(m.Fragment,null)};const K=()=>m.createElement("header",{className:"h-18 flex items-center pl-6 pr-8 bg-accent-primary"},m.createElement(p,{to:"/"},m.createElement("img",{src:"/assets/logo_white.98008342.svg",alt:"isucondition",className:"h-11 cursor-pointer"})),m.createElement(H,null)),X=e=>{var t=e,{label:a,children:r,customClass:c}=t,o=((e,t)=>{var a={};for(var r in e)n.call(e,r)&&t.indexOf(r)<0&&(a[r]=e[r]);if(null!=e&&l)for(var r of l(e))t.indexOf(r)<0&&s.call(e,r)&&(a[r]=e[r]);return a})(t,["label","children","customClass"]);return m.createElement("button",i({className:"flex items-center justify-center focus:outline-none disabled:opacity-40 disabled:cursor-default "+c},o),r||a)},Y=({children:e})=>m.createElement("div",{className:"px-16 py-12 w-full max-w-4xl bg-secondary border border-outline rounded"},e);const Q=()=>m.createElement(Y,null,m.createElement("div",{className:"flex flex-col items-center w-full"},m.createElement("img",{src:"/assets/logo_orange.974bf3e6.svg",alt:"isucondition",className:"my-2 max-w-sm"}),m.createElement("div",{className:"mt-4 text-lg"},"ISUとつくる新しい明日"),m.createElement("div",{className:"mt-16 w-full border-b border-outline"}),m.createElement(X,{label:"JIAのアカウントでログイン",customClass:"mt-10 px-5 py-2 h-12 text-white-primary font-bold bg-button rounded-3xl",onClick:async()=>{location.href=`${location.protocol}//${document.domain}:5000?callback=${location.protocol}//${location.host}`}}))),W=({isu:e})=>m.createElement(p,{to:`/isu/${e.jia_isu_uuid}`,className:"flex flex-col items-center"},m.createElement("img",{src:`/api/isu/${e.jia_isu_uuid}/icon`,className:"w-48 h-48 object-contain",key:e.jia_isu_uuid}),m.createElement("h3",null,e.name)),ee=({variant:e,label:t})=>{const a=`h-6 rounded-2xl px-4 font-medium text-center ${(()=>{switch(e){case"info":return"bg-status-info text-status-info";case"warning":return"bg-status-warning text-status-warning";case"sitting":return"bg-status-sitting text-status-sitting";case"critical":return"bg-status-critical text-status-critical"}})()}`;return m.createElement("div",{className:a},null!=t?t:e)},te=({isus:e})=>m.createElement("div",{className:"grid gap-8 grid-cols-isus w-full"},e.map((e=>m.createElement("div",{key:e.jia_isu_uuid,className:"flex flex-col items-center"},m.createElement(W,{isu:e}),e.latest_isu_condition?m.createElement("div",null,V(e.latest_isu_condition.date)):null,e.latest_isu_condition?m.createElement(ee,{variant:e.latest_isu_condition.condition_level}):null)))),ae=()=>{const[e,t]=o.exports.useState([]);return o.exports.useEffect((()=>{(async()=>{t(await R.getIsus({limit:4}))})()}),[t]),m.createElement("div",null,m.createElement("h2",{className:"mb-6 text-xl font-bold"},"ISU"),m.createElement(te,{isus:e}),m.createElement("div",{className:"flex gap-12 items-center justify-center mt-8"}))},le=()=>{const e="bg-accent-primary opacity-80 w-4 h-35 m-2 rounded-md inline-block";return m.createElement("div",{className:"h-100 flex items-center justify-center"},m.createElement("span",null,m.createElement("span",{className:e+" animate-loader0"}),m.createElement("span",{className:e+" animate-loader1"}),m.createElement("span",{className:e+" animate-loader2"}),m.createElement("span",{className:e+" animate-loader3"}),m.createElement("span",{className:e+" animate-loader4"})))},ne=(e,t)=>`${Math.round(e/t*100)}%`,se=({trend:e,maxConditionCount:t})=>m.createElement("div",{className:"flex items-center w-full h-4"},m.createElement("div",{className:"h-full bg-status-info",style:{width:ne(e.info.length,t)}}),m.createElement("div",{className:"h-full bg-status-warning",style:{width:ne(e.warning.length,t)}}),m.createElement("div",{className:"h-full bg-status-critical",style:{width:ne(e.critical.length,t)}})),re=({trend:e,maxConditionCount:t})=>m.createElement("div",{className:"grid grid-cols-trend p-2"},m.createElement("div",{className:"flex flex-col"},m.createElement("div",null,e.character),m.createElement("div",{className:"text-secondary"},(e=>{let t=null;for(const a of[e.info,e.warning,e.critical].flat())(!t||t<a.date)&&(t=a.date);return t?V(t):"no data"})(e))),m.createElement("div",{className:"flex items-center"},m.createElement(se,{trend:e,maxConditionCount:t}))),ie=()=>m.createElement("div",{className:"grid grid-cols-trend p-2"},m.createElement("div",{className:"flex justify-center"},m.createElement("div",null,"せいかく")),m.createElement("div",{className:"flex gap-4 items-center justify-center"},m.createElement(ee,{variant:"info",label:"バッチリ"}),m.createElement(ee,{variant:"warning",label:"ぼちぼち"}),m.createElement(ee,{variant:"critical",label:"こわれた"}))),ce=e=>e.info.length+e.warning.length+e.critical.length,oe=()=>{const[e,t]=o.exports.useState([]),[a,l]=o.exports.useState(0);return o.exports.useEffect((()=>{(async()=>{const e=await R.getTrend();e.sort(((e,t)=>ce(t)-ce(e))),t(e);let a=0;e.forEach((e=>{const t=ce(e);t>a&&(a=t)})),l(a)})()}),[]),0===e.length?m.createElement(le,null):m.createElement("div",null,m.createElement("h2",{className:"mb-6 text-xl font-bold"},"みんなのISU"),m.createElement(ie,null),e.map((e=>m.createElement(re,{key:e.character,trend:e,maxConditionCount:a}))))},me=()=>U().me?m.createElement(de,null):m.createElement(ue,null),ue=()=>m.createElement("div",{className:"flex flex-col gap-10 items-center p-10"},m.createElement(Q,null),m.createElement(Y,null,m.createElement(oe,null))),de=()=>m.createElement("div",{className:"flex flex-col gap-10 items-center p-10"},m.createElement(Y,null,m.createElement(ae,null))),pe=({to:e,label:t})=>{const{pathname:a}=x(),l=a===e;return m.createElement("div",{className:"w-20 flex justify-center "+(l?"border-b-2 text-accent-primary border-accent-primary font-bold":"text-secondary")},m.createElement(p,{to:e},t))},Ee=({id:e})=>m.createElement("div",{className:"flex"},m.createElement(pe,{to:`/isu/${e}`,label:"詳細"}),m.createElement(pe,{to:`/isu/${e}/condition`,label:"状態"}),m.createElement(pe,{to:`/isu/${e}/graph`,label:"グラフ"})),fe=({isu:e})=>m.createElement("header",{className:"pb-0 pl-12 pt-8 bg-secondary"},m.createElement("h2",{className:"mb-3 text-2xl font-bold"},e.name),m.createElement("div",{className:"ml-6"},m.createElement(Ee,{id:e.jia_isu_uuid}))),ge=e=>{const{isTryLogin:t,login:a,state:l}=(()=>{const e=U(),t=G(),[a,l]=o.exports.useState(!0),n=o.exports.useCallback((e=>{t({type:"login",user:e}),l(!1)}),[t]);return{isTryLogin:a,login:o.exports.useCallback((async t=>{if(e.me)l(!1);else try{l(!0);try{const e=await R.getUserMe({cancelToken:t});n(e)}catch{const e=new URL(location.href),a=e.searchParams.get("jwt");if(!a)return void l(!1);e.searchParams.delete("jwt"),history.replaceState(null,"",e.href),await R.postAuth(a,{cancelToken:t});const s=await R.getUserMe({cancelToken:t});n(s)}}catch{l(!1)}}),[e.me,n]),state:e}})();return o.exports.useEffect((()=>{const e=u.CancelToken.source();return a(e.token),()=>e.cancel()}),[a]),t?m.createElement(le,null):l.me?m.createElement(h,i({},e)):"/login"===e.path?m.createElement(v,{to:"/login"}):"/"===e.path?m.createElement(h,i({},e)):m.createElement(v,{to:"/"})},xe=({conditions:e,next:t,prev:a,page:l})=>{const n=20===e.length,s=l>1;return m.createElement("div",{className:"flex gap-4"},m.createElement(X,{label:"Prev",disabled:!s,onClick:a},m.createElement(y,{size:24})),m.createElement("div",{className:"align-middle text-xl"},l),m.createElement(X,{label:"Next",disabled:!n,onClick:t},m.createElement(b,{size:24})))},ve=({name:e,status:t})=>{const a=(()=>{switch(e){case"is_dirty":return m.createElement(_,{size:20});case"is_overweight":return m.createElement(N,{size:20});case"is_broken":return m.createElement(w,{size:20})}})(),l=`${(()=>{switch(t){case!0:return"text-primary";case!1:return"text-teritary"}})()}`;return m.createElement("div",{className:l},a)},he=({conditionCSV:e})=>{const t=e.split(","),a=[];return t.forEach((e=>{const t=e.split("=");if(2!==t.length)return;const l="true"===t[1];a.push([t[0],l])})),m.createElement("div",{className:"flex"},a.map((e=>m.createElement("div",{key:e[0],className:"px-1"},m.createElement(ve,{name:e[0],status:e[1]})))))},ye=({condition:e})=>m.createElement("div",{className:"flex flex-wrap gap-4 items-center p-4"},m.createElement("div",{className:"mr-auto"},m.createElement("div",null,e.isu_name),m.createElement("div",{className:"text-secondary"},e.message)),m.createElement("div",null,m.createElement(he,{conditionCSV:e.condition})),m.createElement("div",{className:"flex justify-center w-24"},e.is_sitting?m.createElement(ee,{variant:"sitting"}):null),m.createElement("div",{className:"flex justify-center w-24"},m.createElement(ee,{variant:e.condition_level})),m.createElement("div",null,m.createElement("div",null,V(e.date)))),be=({conditions:e})=>m.createElement("div",{className:"flex flex-col gap-4 items-center w-full"},m.createElement("div",{className:"w-full border border-b-0 border-outline"},e.map(((e,t)=>m.createElement("div",{className:"border-b border-outline",key:t},m.createElement(ye,{condition:e})))))),we=({label:e,onClick:t,disabled:a})=>m.createElement(X,{label:e,customClass:"px-3 py-1 h-8 leading-4 border border-outline rounded",onClick:t,disabled:a}),Ne=({label:e,value:t,setValue:a,classname:l,inputProps:n})=>m.createElement("label",{className:"flex flex-col "+l},e,m.createElement("input",c(i({},n),{className:"px-2 py-1 bg-teritary border border-solid border-outline rounded",value:t,onChange:e=>a(e.target.value)}))),_e=({times:e,setTimes:t})=>m.createElement("label",{className:"flex flex-col"},"時間指定",m.createElement("div",{className:"flex items-center"},m.createElement("input",{className:"px-2 py-1 w-40 bg-teritary border-2 border-outline rounded",value:e[0],onChange:a=>t([a.target.value,e[1]]),placeholder:"2020/01/01 11:11:11"}),m.createElement("div",{className:"text-xl"},"~"),m.createElement("input",{className:"px-2 py-1 w-40 bg-teritary border-2 border-outline rounded",value:e[1],onChange:a=>t([e[0],a.target.value]),placeholder:"2020/01/01 11:11:11"}))),Ce=({query:e,times:t,search:a})=>{const[l,n]=o.exports.useState(e),[s,r]=o.exports.useState(t);return m.createElement("div",{className:"flex flex-wrap gap-6 items-end"},m.createElement(Ne,{label:"検索条件",value:l,setValue:n,classname:"flex-1"}),m.createElement(_e,{times:s,setTimes:r}),m.createElement(we,{label:"検索",onClick:()=>a({times:s,query:l}),disabled:!l}))},De=e=>{const t=e.split(",");for(const a of t)if(!["critical","warning","info"].includes(a))return alert("検索条件には critical,warning,info のいずれか一つ以上をカンマ区切りで入力してください"),!1;return!0},Se=e=>{const t=new Date(e);return!isNaN(t.getTime())&&t},je=()=>m.createElement("div",{className:"absolute top-0 flex items-center justify-center w-full h-full bg-gray-500 bg-opacity-25"},m.createElement(le,null)),ke=({isu:e})=>{const[t,a]=o.exports.useState(!1),l=o.exports.useCallback((async t=>{a(!0);const l=await R.getIsuConditions(e.jia_isu_uuid,t);return a(!1),l}),[e]),{conditions:n,query:s,times:r,search:i,next:c,prev:u,page:d}=(e=>{const[t,a]=o.exports.useState([]);o.exports.useEffect((()=>{(async()=>{a(await e({end_time:M(),condition_level:"critical,warning,info"}))})()}),[e,a]);const[l,n]=o.exports.useState("critical,warning,info"),[s,r]=o.exports.useState(["",""]),[i,c]=o.exports.useState([[]]),[m,u]=o.exports.useState(1),d=()=>{const e=s[0]?new Date(s[0]+"Z"):new Date(0);return{end_time:s[1]?new Date(s[1]+"Z"):t[19].date,start_time:e,condition_level:l}};return{conditions:t,query:l,times:s,search:async t=>{if(t.query&&!De(t.query))return;let l,s;if(t.times[0]){const e=Se(t.times[0]+"Z");if(!e)return void alert("時間指定の下限が不正です");l=e}else l=new Date(0);if(t.times[1]){const e=Se(t.times[1]+"Z");if(!e)return void alert("時間指定の上限が不正です");s=e}else s=M();n(t.query),r(t.times);const i={start_time:l,end_time:s,condition_level:t.query};a(await e(i)),u(1),c([[]])},page:m,next:async()=>{i[m]||(i[m]=t,c(i));const l=d();l&&(a(await e(l)),u(m+1))},prev:async()=>{a(i[m-1]),u(m-1)}}})(l);return m.createElement("div",{className:"flex flex-col gap-2"},m.createElement(Ce,{query:s,times:r,search:i}),m.createElement("div",{className:"flex flex-col gap-4 items-center"},m.createElement("div",{className:"relative w-full"},m.createElement(be,{conditions:n}),t?m.createElement(je,null):null),m.createElement(xe,{conditions:n,page:d,next:c,prev:u})))},$e=({isu:e})=>e?m.createElement("div",{className:"flex flex-col gap-10 items-center"},m.createElement(Y,null,m.createElement(ke,{isu:e}))):m.createElement(le,null),Ie=({isu:e,reloadKey:t})=>m.createElement("img",{src:`/api/isu/${e.jia_isu_uuid}/icon`,className:"w-48 h-48 object-contain",key:t}),Oe=({isu:e})=>m.createElement("div",{className:"flex flex-wrap gap-16 justify-center"},m.createElement(Ie,{isu:e}),m.createElement("div",{className:"flex flex-col min-h-full"},m.createElement("div",{className:"text-xl font-bold"},e.name),m.createElement("div",{className:"flex flex-1 mt-4 pl-8"},m.createElement("div",{className:"mr-4"},"せいかく"),m.createElement("div",{className:"flex-1"},e.character)))),Te=({isu:e})=>e?m.createElement("div",{className:"flex flex-col gap-10 items-center"},m.createElement(Y,null,m.createElement(Oe,{isu:e}))):m.createElement(le,null),Pe=({transitionData:e,timeCategories:t,tooltipData:a})=>{const l={chart:{toolbar:{show:!1}},grid:{yaxis:{lines:{show:!1}}},colors:["#008FFB"],series:[{type:"line",data:e}],xaxis:{categories:t},yaxis:{min:0},tooltip:{custom:({dataPointIndex:e})=>qe(a[e])}};return m.createElement("div",null,m.createElement(C,{type:"line",options:l,series:l.series}))},qe=e=>`\n  <div class="flex flex-col px-3 py-1 text-primary">\n    <div class="flex flex-row">\n      <div class="w-25">score</div>\n      <div>${e.score}</div>\n    </div>\n    <div class="flex flex-row">\n      <div class="w-25">is_dirty</div>\n      <div>${e.is_dirty}</div>\n    </div>\n    <div class="flex flex-row">\n      <div class="w-25">is_overweight</div>\n      <div>${e.is_overweight}</div>\n    </div>\n    <div class="flex flex-row">\n      <div class="w-25">is_broken</div>\n      <div>${e.is_broken}</div>\n    </div>\n  </div>`,ze=({sittingData:e,timeCategories:t})=>{const a={chart:{toolbar:{show:!1}},colors:["#ff6433"],series:[{type:"heatmap",data:e,name:""}],xaxis:{categories:t,labels:{show:!1}},plotOptions:{heatmap:{colorScale:{ranges:[{from:0,to:20,color:"#d1d1d1"}]}}}};return m.createElement("div",{style:{transform:"translateX(13px) translateY(-32px) scaleX(0.993)"}},m.createElement(C,{type:"heatmap",options:a,series:a.series}))},Ue=e=>{const[t,a]=o.exports.useState({graphs:[],transitionData:[],sittingData:[],timeCategories:[],day:"",tooltipData:[]}),[l,n]=o.exports.useState((()=>{const e=M();return e.setHours(0,0,0,0),e})());o.exports.useEffect((()=>{(async()=>{const t=await e({date:l}),n=Ge(t);a((e=>c(i({},e),{graphs:t,transitionData:n.transitionData,sittingData:n.sittingData,timeCategories:n.timeCategories,day:l.toLocaleDateString(),tooltipData:n.tooltipData})))})()}),[e,a,l]);const s=async()=>{const t=await e({date:l}),n=Ge(t);a((e=>c(i({},e),{loading:!1,graphs:t,transitionData:n.transitionData,sittingData:n.sittingData,timeCategories:n.timeCategories,day:l.toLocaleTimeString(),tooltipData:n.tooltipData})))};return c(i({},t),{fetchGraphs:async e=>{const t=new Date(e.day);isNaN(t.getTime())?alert("日時の指定が不正です"):(n(t),s())},prev:async()=>{n((e=>new Date(e.setDate(e.getDate()-1)))(l)),s()},next:async()=>{n((e=>new Date(e.setDate(e.getDate()+1)))(l)),s()}})},Ge=e=>{const t=[],a=[],l=[],n=[];return e.forEach((e=>{e.data?(t.push(e.data.score),a.push(e.data.percentage.sitting),n.push({score:e.data.score.toString(),is_dirty:`${e.data.percentage.is_dirty}%`,is_overweight:`${e.data.percentage.is_overweight}%`,is_broken:`${e.data.percentage.is_broken}%`})):(t.push(0),a.push(0),n.push({score:"-",is_dirty:"-",is_overweight:"-",is_broken:"-"})),l.push(e.start_at.toLocaleTimeString("ja-JP",{hour:"2-digit",minute:"2-digit"}))})),{transitionData:t,sittingData:a,timeCategories:l,tooltipData:n}},Le=({day:e,fetchGraphs:t})=>{const[a,l]=o.exports.useState(e);return o.exports.useEffect((()=>{l(e)}),[e,l]),m.createElement("div",{className:"flex gap-8 w-full"},m.createElement(D,{value:a,onChange:e=>l(e.target.value),onKeyPress:e=>{"Enter"===e.key&&(e.preventDefault(),t({day:a}))}}))},Me=({next:e,prev:t,day:a,fetchGraphs:l})=>m.createElement("div",{className:"flex gap-8"},m.createElement(X,{label:"Prev",onClick:t},m.createElement(y,{size:24})),m.createElement(Le,{day:a,fetchGraphs:l}),m.createElement(X,{label:"Next",onClick:e},m.createElement(b,{size:24}))),Ae=({isu:e})=>{const[t,a]=o.exports.useState(!1),l=o.exports.useCallback((async t=>{a(!0);const l=await R.getIsuGraphs(e.jia_isu_uuid,t);return a(!1),l}),[e.jia_isu_uuid]),{graphs:n,transitionData:s,sittingData:r,timeCategories:i,day:c,tooltipData:u,fetchGraphs:d,prev:p,next:E}=Ue(l);return 0===n.length?m.createElement(le,null):m.createElement("div",{className:"flex flex-col gap-12"},m.createElement("div",{className:"flex justify-center w-full"},m.createElement(Me,{prev:p,next:E,day:c,fetchGraphs:d})),m.createElement("div",{className:"relative flex flex-col gap-8"},m.createElement("div",{className:"z-10"},m.createElement(Pe,{transitionData:s,timeCategories:i,tooltipData:u})),m.createElement("div",{className:"absolute top-0 w-full"},m.createElement(ze,{sittingData:r,timeCategories:i})),t?m.createElement(je,null):null))},Fe=({isu:e})=>e?m.createElement("div",{className:"flex flex-col gap-10 items-center"},m.createElement(Y,null,m.createElement(Ae,{isu:e}))):m.createElement(le,null),Ve=()=>{const[e,t]=o.exports.useState(null),{id:a}=S(),[l,n]=o.exports.useState(!1);return o.exports.useEffect((()=>{(async()=>{try{t(await R.getIsu(a))}catch(e){404===e.response.status&&n(!0)}})()}),[a,n]),e?m.createElement("div",null,m.createElement(fe,{isu:e}),m.createElement("div",{className:"p-10"},m.createElement(Be,{isu:e}))):l?m.createElement(v,{to:"/"}):m.createElement(le,null)},Be=({isu:e})=>m.createElement(j,null,m.createElement(ge,{path:"/isu/:id",exact:!0},m.createElement(Te,{isu:e})),m.createElement(ge,{path:"/isu/:id/condition",exact:!0},m.createElement($e,{isu:e})),m.createElement(ge,{path:"/isu/:id/graph",exact:!0},m.createElement(Fe,{isu:e}))),Re=({putIsuIcon:e})=>{const{startSelect:t,destroy:a}=(e=>{const t=document.createElement("input");t.type="file",t.accept="image/jpeg";const a=()=>{t.files&&t.files[0]&&e(t.files[0])};return t.addEventListener("change",a),{startSelect:()=>{t.click()},destroy:()=>{t.removeEventListener("change",a)}}})(e);return o.exports.useEffect((()=>a)),m.createElement(we,{label:"画像をアップロード",onClick:t})},Ze=()=>{const[e,t]=o.exports.useState(""),[a,l]=o.exports.useState(""),[n,s]=o.exports.useState(null),r=k();return m.createElement("div",{className:"flex justify-center p-10"},m.createElement("div",{className:"flex justify-center w-full max-w-2xl"},m.createElement(Y,null,m.createElement("div",{className:"w-full"},m.createElement("h2",{className:"mb-8 text-xl font-bold"},"ISUを登録"),m.createElement("div",{className:"flex flex-col gap-4"},m.createElement(Ne,{label:"JIAのIsuID",value:e,setValue:t}),m.createElement(Ne,{label:"ISUの名前",value:a,setValue:l}),m.createElement("div",{className:"flex flex-col gap-8 items-center mt-6"},m.createElement(Re,{putIsuIcon:s}),m.createElement(X,{label:"登録",onClick:async()=>{try{const t={jia_isu_uuid:e,isu_name:a};n&&(t.image=n),await R.postIsu(t),r.push(`/isu/${e}`)}catch(t){409===t.response.status?r.push(`/isu/${e}`):alert(t.response.data)}},customClass:"px-4 py-1 h-8 text-white-primary font-bold bg-button rounded-2xl",disabled:!e||!a})))))))},Je=()=>m.createElement("div",{className:"flex flex-col min-h-full text-primary"},m.createElement($,null,m.createElement(K,null),m.createElement("div",{className:"flex-1 bg-primary"},m.createElement(j,null,m.createElement(ge,{path:"/",exact:!0},m.createElement(me,null)),m.createElement(ge,{path:"/isu/:id"},m.createElement(Ve,null)),m.createElement(ge,{path:"/register",exact:!0},m.createElement(Ze,null)),m.createElement(h,null,m.createElement(v,{to:"/"}))))));I.render(m.createElement(o.exports.StrictMode,null,m.createElement(z,null,m.createElement(Je,null))),document.getElementById("root")),d.setAppElement("#root");
+var e=Object.defineProperty,t=Object.defineProperties,a=Object.getOwnPropertyDescriptors,l=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,s=Object.prototype.propertyIsEnumerable,r=(t,a,l)=>a in t?e(t,a,{enumerable:!0,configurable:!0,writable:!0,value:l}):t[a]=l,i=(e,t)=>{for(var a in t||(t={}))n.call(t,a)&&r(e,a,t[a]);if(l)for(var a of l(t))s.call(t,a)&&r(e,a,t[a]);return e},c=(e,l)=>t(e,a(l));import{r as o,R as m,a as u,M as d,L as p,I as E,T as f,b as g,u as x,c as v,d as h,e as y,f as b,g as w,F as N,G as _,_ as C,h as D,i as S,S as j,j as k,B as $,k as I}from"./vendor.f1db1b60.js";const O={me:null},T=o.exports.createContext(O),P=o.exports.createContext(null),q=(e,t)=>{switch(t.type){case"login":return c(i({},e),{me:t.user});case"logout":return c(i({},e),{me:null});default:throw new Error("invalid action")}},z=({children:e})=>{const[t,a]=o.exports.useReducer(q,O);return m.createElement(T.Provider,{value:t},m.createElement(P.Provider,{value:a},e))},U=()=>{const e=o.exports.useContext(T);if(!e)throw new Error("require wrapped by stateContext");return e},G=()=>{const e=o.exports.useContext(P);if(!e)throw new Error("require wrapped by stateContext");return e},L=({children:e})=>m.createElement("div",{className:"text-white-primary font-bold"},e),M=()=>new Date,A=e=>Math.floor(e.getTime()/1e3),F=e=>new Date(1e3*e),V=e=>`${e.getFullYear()}/${B(e.getMonth()+1)}/${B(e.getDate())} ${B(e.getHours())}:${B(e.getMinutes())}:${B(e.getSeconds())}`,B=e=>("0"+e).slice(-2);const R=new class{async postAuth(e,t){await u.post("/api/auth",{},i({headers:{Authorization:`Bearer ${e}`}},t))}async postSignout(e){await u.post("/api/signout",e)}async getUserMe(e){const{data:t}=await u.get("/api/user/me",e);return t}async getIsus(e,t){const{data:a}=await u.get("/api/isu",i({params:e},t)),l=[];for(const n of a)l.push(c(i({},n),{latest_isu_condition:n.latest_isu_condition?c(i({},n.latest_isu_condition),{date:F(n.latest_isu_condition.timestamp)}):null}));return l}async postIsu(e,t){const a=new FormData;a.append("jia_isu_uuid",e.jia_isu_uuid),a.append("isu_name",e.isu_name),e.image&&a.append("image",e.image,e.image.name),await u.post("/api/isu",a,i({headers:{"content-type":"multipart/form-data"}},t))}async getIsu(e,t){const{data:a}=await u.get(`/api/isu/${e}`,t);return a}async deleteIsu(e,t){await u.delete(`/api/isu/${e}`,t)}async getIsuGraphs(e,t,a){const l={datetime:A(t.date)},{data:n}=await u.get(`/api/isu/${e}/graph`,i({params:l},a)),s=[];return n.forEach((e=>{s.push(c(i({},e),{start_at:F(e.start_at),end_at:F(e.end_at)}))})),s}async getIsuConditions(e,t,a){const l=c(i({},t),{start_time:t.start_time?A(t.start_time):void 0,end_time:A(t.end_time)}),{data:n}=await u.get(`/api/condition/${e}`,i({params:l},a)),s=[];return n.forEach((e=>{s.push(c(i({},e),{date:F(e.timestamp)}))})),s}async getTrend(e){const{data:t}=await u.get("/api/trend",i({},e)),a=[];return t.forEach((e=>{const t=[],l=[],n=[];e.info.forEach((e=>{t.push(c(i({},e),{date:F(e.timestamp)}))})),e.warning.forEach((e=>{l.push(c(i({},e),{date:F(e.timestamp)}))})),e.critical.forEach((e=>{n.push(c(i({},e),{date:F(e.timestamp)}))})),a.push(c(i({},e),{info:t,warning:l,critical:n}))})),a}},Z=e=>{const t=G();return m.createElement(d,{isOpen:e.isOpen,onRequestClose:e.toggle,className:"top-18 bg-gray-50 absolute right-0 flex justify-items-center px-6 py-3 border border-outline rounded",overlayClassName:"fixed inset-0",shouldCloseOnOverlayClick:!0},m.createElement(p,{to:"/",onClick:async()=>{await R.postSignout(),t({type:"logout"})},className:"flex items-center text-primary"},m.createElement(E,{className:"mr-1",size:16}),m.createElement("div",null,"logout")))},J=e=>m.createElement(L,null,m.createElement(p,{to:e.to,className:"flex items-center"},e.icon,m.createElement("div",{className:"ml-1"},e.label))),X=()=>{const[e,t]=o.exports.useState(!1),a=()=>{t(!e)},l=U().me;return l?m.createElement("div",{className:"w-52 flex items-center justify-between ml-auto"},m.createElement(J,{to:"/register",label:"ISUの登録",icon:m.createElement(f,null)}),m.createElement("div",{className:"border-l-1 pl-4 border-white"},m.createElement(L,null,m.createElement("div",{className:"flex items-center cursor-pointer",onClick:a},m.createElement(g,null),m.createElement("div",{className:"ml-1"},l.jia_user_id)))),m.createElement(Z,{isOpen:e,toggle:a})):m.createElement(m.Fragment,null)};const Y=()=>m.createElement("header",{className:"h-18 flex items-center pl-6 pr-8 bg-accent-primary"},m.createElement(p,{to:"/"},m.createElement("img",{src:"/assets/logo_white.98008342.svg",alt:"isucondition",className:"h-11 cursor-pointer"})),m.createElement(X,null)),H=e=>{var t=e,{label:a,children:r,customClass:c}=t,o=((e,t)=>{var a={};for(var r in e)n.call(e,r)&&t.indexOf(r)<0&&(a[r]=e[r]);if(null!=e&&l)for(var r of l(e))t.indexOf(r)<0&&s.call(e,r)&&(a[r]=e[r]);return a})(t,["label","children","customClass"]);return m.createElement("button",i({className:"flex items-center justify-center focus:outline-none disabled:opacity-40 disabled:cursor-default "+c},o),r||a)},K=({children:e})=>m.createElement("div",{className:"px-16 py-12 w-full max-w-4xl bg-secondary border border-outline rounded"},e);const Q=()=>m.createElement(K,null,m.createElement("div",{className:"flex flex-col items-center w-full"},m.createElement("img",{src:"/assets/logo_orange.974bf3e6.svg",alt:"isucondition",className:"my-2 max-w-sm"}),m.createElement("div",{className:"mt-4 text-lg"},"ISUとつくる新しい明日"),m.createElement("div",{className:"mt-16 w-full border-b border-outline"}),m.createElement(H,{label:"JIAのアカウントでログイン",customClass:"mt-10 px-5 py-2 h-12 text-white-primary font-bold bg-button rounded-3xl",onClick:async()=>{location.href=`${location.protocol}//${document.domain}:5000?callback=${location.protocol}//${location.host}`}}))),W=({isu:e})=>m.createElement(p,{to:`/isu/${e.jia_isu_uuid}`,className:"flex flex-col items-center"},m.createElement("img",{src:`/api/isu/${e.jia_isu_uuid}/icon`,className:"w-48 h-48 object-contain",key:e.jia_isu_uuid}),m.createElement("h3",null,e.name)),ee=({variant:e,label:t})=>{const a=`h-6 rounded-2xl px-4 font-medium text-center ${(()=>{switch(e){case"info":return"bg-status-info text-status-info";case"warning":return"bg-status-warning text-status-warning";case"sitting":return"bg-status-sitting text-status-sitting";case"critical":return"bg-status-critical text-status-critical"}})()}`;return m.createElement("div",{className:a},null!=t?t:e)},te=({isus:e})=>m.createElement("div",{className:"grid gap-8 grid-cols-isus w-full"},e.map((e=>m.createElement("div",{key:e.jia_isu_uuid,className:"flex flex-col items-center"},m.createElement(W,{isu:e}),e.latest_isu_condition?m.createElement("div",null,V(e.latest_isu_condition.date)):null,e.latest_isu_condition?m.createElement(ee,{variant:e.latest_isu_condition.condition_level}):null)))),ae=()=>{const[e,t]=o.exports.useState([]);return o.exports.useEffect((()=>{(async()=>{t(await R.getIsus({limit:4}))})()}),[t]),m.createElement("div",null,m.createElement("h2",{className:"mb-6 text-xl font-bold"},"ISU"),m.createElement(te,{isus:e}),m.createElement("div",{className:"flex gap-12 items-center justify-center mt-8"}))},le=()=>{const e="bg-accent-primary opacity-80 w-4 h-35 m-2 rounded-md inline-block";return m.createElement("div",{className:"h-100 flex items-center justify-center"},m.createElement("span",null,m.createElement("span",{className:e+" animate-loader0"}),m.createElement("span",{className:e+" animate-loader1"}),m.createElement("span",{className:e+" animate-loader2"}),m.createElement("span",{className:e+" animate-loader3"}),m.createElement("span",{className:e+" animate-loader4"})))},ne=(e,t)=>`${Math.round(e/t*100)}%`,se=({trend:e,maxConditionCount:t})=>m.createElement("div",{className:"flex items-center w-full h-4"},m.createElement("div",{className:"h-full bg-status-info",style:{width:ne(e.info.length,t)}}),m.createElement("div",{className:"h-full bg-status-warning",style:{width:ne(e.warning.length,t)}}),m.createElement("div",{className:"h-full bg-status-critical",style:{width:ne(e.critical.length,t)}})),re=({trend:e,maxConditionCount:t})=>m.createElement("div",{className:"grid grid-cols-trend p-2"},m.createElement("div",{className:"flex flex-col"},m.createElement("div",null,e.character),m.createElement("div",{className:"text-secondary"},(e=>{let t=null;for(const a of[e.info,e.warning,e.critical].flat())(!t||t<a.date)&&(t=a.date);return t?V(t):"no data"})(e))),m.createElement("div",{className:"flex items-center"},m.createElement(se,{trend:e,maxConditionCount:t}))),ie=()=>m.createElement("div",{className:"grid grid-cols-trend p-2"},m.createElement("div",{className:"flex justify-center"},m.createElement("div",null,"せいかく")),m.createElement("div",{className:"flex gap-4 items-center justify-center"},m.createElement(ee,{variant:"info",label:"バッチリ"}),m.createElement(ee,{variant:"warning",label:"ぼちぼち"}),m.createElement(ee,{variant:"critical",label:"こわれた"}))),ce=e=>e.info.length+e.warning.length+e.critical.length,oe=()=>{const[e,t]=o.exports.useState([]),[a,l]=o.exports.useState(0);return o.exports.useEffect((()=>{(async()=>{const e=await R.getTrend();e.sort(((e,t)=>ce(t)-ce(e))),t(e);let a=0;e.forEach((e=>{const t=ce(e);t>a&&(a=t)})),l(a)})()}),[]),0===e.length?m.createElement(le,null):m.createElement("div",null,m.createElement("h2",{className:"mb-6 text-xl font-bold"},"みんなのISU"),m.createElement(ie,null),e.map((e=>m.createElement(re,{key:e.character,trend:e,maxConditionCount:a}))))},me=()=>U().me?m.createElement(de,null):m.createElement(ue,null),ue=()=>m.createElement("div",{className:"flex flex-col gap-10 items-center p-10"},m.createElement(Q,null),m.createElement(K,null,m.createElement(oe,null))),de=()=>m.createElement("div",{className:"flex flex-col gap-10 items-center p-10"},m.createElement(K,null,m.createElement(ae,null))),pe=({to:e,label:t})=>{const{pathname:a}=x(),l=a===e;return m.createElement("div",{className:"w-20 flex justify-center "+(l?"border-b-2 text-accent-primary border-accent-primary font-bold":"text-secondary")},m.createElement(p,{to:e},t))},Ee=({id:e})=>m.createElement("div",{className:"flex"},m.createElement(pe,{to:`/isu/${e}`,label:"詳細"}),m.createElement(pe,{to:`/isu/${e}/condition`,label:"状態"}),m.createElement(pe,{to:`/isu/${e}/graph`,label:"グラフ"})),fe=({isu:e})=>m.createElement("header",{className:"pb-0 pl-12 pt-8 bg-secondary"},m.createElement("h2",{className:"mb-3 text-2xl font-bold"},e.name),m.createElement("div",{className:"ml-6"},m.createElement(Ee,{id:e.jia_isu_uuid}))),ge=e=>{const{isTryLogin:t,login:a,state:l}=(()=>{const e=U(),t=G(),[a,l]=o.exports.useState(!0),n=o.exports.useCallback((e=>{t({type:"login",user:e}),l(!1)}),[t]);return{isTryLogin:a,login:o.exports.useCallback((async t=>{if(e.me)l(!1);else try{l(!0);try{const e=await R.getUserMe({cancelToken:t});n(e)}catch{const e=new URL(location.href),a=e.searchParams.get("jwt");if(!a)return void l(!1);e.searchParams.delete("jwt"),history.replaceState(null,"",e.href),await R.postAuth(a,{cancelToken:t});const s=await R.getUserMe({cancelToken:t});n(s)}}catch{l(!1)}}),[e.me,n]),state:e}})();return o.exports.useEffect((()=>{const e=u.CancelToken.source();return a(e.token),()=>e.cancel()}),[a]),t?m.createElement(le,null):l.me?m.createElement(h,i({},e)):"/login"===e.path?m.createElement(v,{to:"/login"}):"/"===e.path?m.createElement(h,i({},e)):m.createElement(v,{to:"/"})},xe=({conditions:e,next:t,prev:a,page:l})=>{const n=20===e.length,s=l>1;return m.createElement("div",{className:"flex gap-4"},m.createElement(H,{label:"Prev",disabled:!s,onClick:a},m.createElement(y,{size:24})),m.createElement("div",{className:"align-middle text-xl"},l),m.createElement(H,{label:"Next",disabled:!n,onClick:t},m.createElement(b,{size:24})))},ve=({name:e,status:t})=>{const a=(()=>{switch(e){case"is_dirty":return m.createElement(_,{size:20});case"is_overweight":return m.createElement(N,{size:20});case"is_broken":return m.createElement(w,{size:20})}})(),l=`${(()=>{switch(t){case!0:return"text-primary";case!1:return"text-teritary"}})()}`;return m.createElement("div",{className:l},a)},he=({conditionCSV:e})=>{const t=e.split(","),a=[];return t.forEach((e=>{const t=e.split("=");if(2!==t.length)return;const l="true"===t[1];a.push([t[0],l])})),m.createElement("div",{className:"flex"},a.map((e=>m.createElement("div",{key:e[0],className:"px-1"},m.createElement(ve,{name:e[0],status:e[1]})))))},ye=({condition:e})=>m.createElement("div",{className:"flex flex-wrap gap-4 items-center p-4"},m.createElement("div",{className:"mr-auto"},m.createElement("div",null,e.isu_name),m.createElement("div",{className:"text-secondary"},e.message)),m.createElement("div",null,m.createElement(he,{conditionCSV:e.condition})),m.createElement("div",{className:"flex justify-center w-24"},e.is_sitting?m.createElement(ee,{variant:"sitting"}):null),m.createElement("div",{className:"flex justify-center w-24"},m.createElement(ee,{variant:e.condition_level})),m.createElement("div",null,m.createElement("div",null,V(e.date)))),be=({conditions:e})=>m.createElement("div",{className:"flex flex-col gap-4 items-center w-full"},m.createElement("div",{className:"w-full border border-b-0 border-outline"},e.map(((e,t)=>m.createElement("div",{className:"border-b border-outline",key:t},m.createElement(ye,{condition:e})))))),we=({label:e,onClick:t,disabled:a})=>m.createElement(H,{label:e,customClass:"px-3 py-1 h-8 leading-4 border border-outline rounded",onClick:t,disabled:a}),Ne=({label:e,value:t,setValue:a,classname:l,inputProps:n})=>m.createElement("label",{className:"flex flex-col "+l},e,m.createElement("input",c(i({},n),{className:"px-2 py-1 bg-teritary border border-solid border-outline rounded",value:t,onChange:e=>a(e.target.value)}))),_e=({times:e,setTimes:t})=>m.createElement("label",{className:"flex flex-col"},"時間指定",m.createElement("div",{className:"flex items-center"},m.createElement("input",{className:"px-2 py-1 w-40 bg-teritary border-2 border-outline rounded",value:e[0],onChange:a=>t([a.target.value,e[1]]),placeholder:"2020/01/01 11:11:11"}),m.createElement("div",{className:"text-xl"},"~"),m.createElement("input",{className:"px-2 py-1 w-40 bg-teritary border-2 border-outline rounded",value:e[1],onChange:a=>t([e[0],a.target.value]),placeholder:"2020/01/01 11:11:11"}))),Ce=({query:e,times:t,search:a})=>{const[l,n]=o.exports.useState(e),[s,r]=o.exports.useState(t);return m.createElement("div",{className:"flex flex-wrap gap-6 items-end"},m.createElement(Ne,{label:"検索条件",value:l,setValue:n,classname:"flex-1"}),m.createElement(_e,{times:s,setTimes:r}),m.createElement(we,{label:"検索",onClick:()=>a({times:s,query:l}),disabled:!l}))},De=e=>{const t=e.split(",");for(const a of t)if(!["critical","warning","info"].includes(a))return alert("検索条件には critical,warning,info のいずれか一つ以上をカンマ区切りで入力してください"),!1;return!0},Se=e=>{const t=new Date(e);return!isNaN(t.getTime())&&t},je=()=>m.createElement("div",{className:"absolute top-0 flex items-center justify-center w-full h-full bg-gray-500 bg-opacity-25"},m.createElement(le,null)),ke=({isu:e})=>{const[t,a]=o.exports.useState(!1),l=o.exports.useCallback((async t=>{a(!0);const l=await R.getIsuConditions(e.jia_isu_uuid,t);return a(!1),l}),[e]),{conditions:n,query:s,times:r,search:i,next:c,prev:u,page:d}=(e=>{const[t,a]=o.exports.useState([]);o.exports.useEffect((()=>{(async()=>{a(await e({end_time:M(),condition_level:"critical,warning,info"}))})()}),[e,a]);const[l,n]=o.exports.useState("critical,warning,info"),[s,r]=o.exports.useState(["",""]),[i,c]=o.exports.useState([[]]),[m,u]=o.exports.useState(1),d=()=>{const e=s[0]?new Date(s[0]+"Z"):new Date(0);return{end_time:s[1]?new Date(s[1]+"Z"):t[19].date,start_time:e,condition_level:l}};return{conditions:t,query:l,times:s,search:async t=>{if(t.query&&!De(t.query))return;let l,s;if(t.times[0]){const e=Se(t.times[0]+"Z");if(!e)return void alert("時間指定の下限が不正です");l=e}else l=new Date(0);if(t.times[1]){const e=Se(t.times[1]+"Z");if(!e)return void alert("時間指定の上限が不正です");s=e}else s=M();n(t.query),r(t.times);const i={start_time:l,end_time:s,condition_level:t.query};a(await e(i)),u(1),c([[]])},page:m,next:async()=>{i[m]||(i[m]=t,c(i));const l=d();l&&(a(await e(l)),u(m+1))},prev:async()=>{a(i[m-1]),u(m-1)}}})(l);return m.createElement("div",{className:"flex flex-col gap-2"},m.createElement(Ce,{query:s,times:r,search:i}),m.createElement("div",{className:"flex flex-col gap-4 items-center"},m.createElement("div",{className:"relative w-full"},m.createElement(be,{conditions:n}),t?m.createElement(je,null):null),m.createElement(xe,{conditions:n,page:d,next:c,prev:u})))},$e=({isu:e})=>e?m.createElement("div",{className:"flex flex-col gap-10 items-center"},m.createElement(K,null,m.createElement(ke,{isu:e}))):m.createElement(le,null),Ie=({isu:e,reloadKey:t})=>m.createElement("img",{src:`/api/isu/${e.jia_isu_uuid}/icon`,className:"w-48 h-48 object-contain",key:t}),Oe=({isu:e})=>m.createElement("div",{className:"flex flex-wrap gap-16 justify-center"},m.createElement(Ie,{isu:e}),m.createElement("div",{className:"flex flex-col min-h-full"},m.createElement("div",{className:"text-xl font-bold"},e.name),m.createElement("div",{className:"flex flex-1 mt-4 pl-8"},m.createElement("div",{className:"mr-4"},"せいかく"),m.createElement("div",{className:"flex-1"},e.character)))),Te=({isu:e})=>e?m.createElement("div",{className:"flex flex-col gap-10 items-center"},m.createElement(K,null,m.createElement(Oe,{isu:e}))):m.createElement(le,null),Pe=({transitionData:e,timeCategories:t,tooltipData:a})=>{const l={chart:{toolbar:{show:!1}},grid:{yaxis:{lines:{show:!1}}},colors:["#008FFB"],series:[{type:"line",data:e}],xaxis:{categories:t,offsetY:8},yaxis:{min:0,labels:{offsetX:-16}},tooltip:{custom:({dataPointIndex:e})=>qe(a[e])}};return m.createElement("div",null,m.createElement(C,{type:"line",options:l,series:l.series}))},qe=e=>`\n  <div class="flex flex-col px-3 py-1 text-primary">\n    <div class="flex flex-row">\n      <div class="w-25">score</div>\n      <div>${e.score}</div>\n    </div>\n    <div class="flex flex-row">\n      <div class="w-25">is_dirty</div>\n      <div>${e.is_dirty}</div>\n    </div>\n    <div class="flex flex-row">\n      <div class="w-25">is_overweight</div>\n      <div>${e.is_overweight}</div>\n    </div>\n    <div class="flex flex-row">\n      <div class="w-25">is_broken</div>\n      <div>${e.is_broken}</div>\n    </div>\n  </div>`,ze=({sittingData:e,timeCategories:t})=>{const a={chart:{toolbar:{show:!1}},colors:["#ff6433"],series:[{type:"heatmap",data:e,name:""}],xaxis:{categories:t,labels:{show:!1},axisBorder:{show:!1},axisTicks:{show:!1}},plotOptions:{heatmap:{colorScale:{ranges:[{from:0,to:20,color:"#d1d1d1"}]}}}};return m.createElement("div",{style:{transform:"translateX(13px) translateY(-32px) scaleX(1.04)"}},m.createElement(C,{type:"heatmap",options:a,series:a.series}))},Ue=e=>{const[t,a]=o.exports.useState({graphs:[],transitionData:[],sittingData:[],timeCategories:[],day:"",tooltipData:[]}),[l,n]=o.exports.useState((()=>{const e=M();return e.setHours(0,0,0,0),e})());o.exports.useEffect((()=>{(async()=>{const t=await e({date:l}),n=Ge(t);a((e=>c(i({},e),{graphs:t,transitionData:n.transitionData,sittingData:n.sittingData,timeCategories:n.timeCategories,day:l.toLocaleDateString(),tooltipData:n.tooltipData})))})()}),[e,a,l]);const s=async()=>{const t=await e({date:l}),n=Ge(t);a((e=>c(i({},e),{loading:!1,graphs:t,transitionData:n.transitionData,sittingData:n.sittingData,timeCategories:n.timeCategories,day:l.toLocaleTimeString(),tooltipData:n.tooltipData})))};return c(i({},t),{fetchGraphs:async e=>{const t=new Date(e.day);isNaN(t.getTime())?alert("日時の指定が不正です"):(n(t),s())},prev:async()=>{n((e=>new Date(e.setDate(e.getDate()-1)))(l)),s()},next:async()=>{n((e=>new Date(e.setDate(e.getDate()+1)))(l)),s()}})},Ge=e=>{const t=[],a=[],l=[],n=[];return e.forEach((e=>{e.data?(t.push(e.data.score),a.push(e.data.percentage.sitting),n.push({score:e.data.score.toString(),is_dirty:`${e.data.percentage.is_dirty}%`,is_overweight:`${e.data.percentage.is_overweight}%`,is_broken:`${e.data.percentage.is_broken}%`})):(t.push(0),a.push(0),n.push({score:"-",is_dirty:"-",is_overweight:"-",is_broken:"-"})),l.push(e.start_at.toLocaleTimeString("ja-JP",{hour:"2-digit",minute:"2-digit"}))})),{transitionData:t,sittingData:a,timeCategories:l,tooltipData:n}},Le=({day:e,fetchGraphs:t})=>{const[a,l]=o.exports.useState(e);return o.exports.useEffect((()=>{l(e)}),[e,l]),m.createElement("div",{className:"flex gap-8 w-full"},m.createElement(D,{value:a,onChange:e=>l(e.target.value),onKeyPress:e=>{"Enter"===e.key&&(e.preventDefault(),t({day:a}))}}))},Me=({next:e,prev:t,day:a,fetchGraphs:l})=>m.createElement("div",{className:"flex gap-8"},m.createElement(H,{label:"Prev",onClick:t},m.createElement(y,{size:24})),m.createElement(Le,{day:a,fetchGraphs:l}),m.createElement(H,{label:"Next",onClick:e},m.createElement(b,{size:24}))),Ae=({isu:e})=>{const[t,a]=o.exports.useState(!1),l=o.exports.useCallback((async t=>{a(!0);const l=await R.getIsuGraphs(e.jia_isu_uuid,t);return a(!1),l}),[e.jia_isu_uuid]),{graphs:n,transitionData:s,sittingData:r,timeCategories:i,day:c,tooltipData:u,fetchGraphs:d,prev:p,next:E}=Ue(l);return 0===n.length?m.createElement(le,null):m.createElement("div",{className:"flex flex-col gap-12"},m.createElement("div",{className:"flex justify-center w-full"},m.createElement(Me,{prev:p,next:E,day:c,fetchGraphs:d})),m.createElement("div",{className:"relative flex flex-col gap-8"},m.createElement("div",{className:"z-10"},m.createElement(Pe,{transitionData:s,timeCategories:i,tooltipData:u})),m.createElement("div",{className:"absolute top-0 w-full"},m.createElement(ze,{sittingData:r,timeCategories:i})),t?m.createElement(je,null):null))},Fe=({isu:e})=>e?m.createElement("div",{className:"flex flex-col gap-10 items-center"},m.createElement(K,null,m.createElement(Ae,{isu:e}))):m.createElement(le,null),Ve=()=>{const[e,t]=o.exports.useState(null),{id:a}=S(),[l,n]=o.exports.useState(!1);return o.exports.useEffect((()=>{(async()=>{try{t(await R.getIsu(a))}catch(e){404===e.response.status&&n(!0)}})()}),[a,n]),e?m.createElement("div",null,m.createElement(fe,{isu:e}),m.createElement("div",{className:"p-10"},m.createElement(Be,{isu:e}))):l?m.createElement(v,{to:"/"}):m.createElement(le,null)},Be=({isu:e})=>m.createElement(j,null,m.createElement(ge,{path:"/isu/:id",exact:!0},m.createElement(Te,{isu:e})),m.createElement(ge,{path:"/isu/:id/condition",exact:!0},m.createElement($e,{isu:e})),m.createElement(ge,{path:"/isu/:id/graph",exact:!0},m.createElement(Fe,{isu:e}))),Re=({putIsuIcon:e})=>{const{startSelect:t,destroy:a}=(e=>{const t=document.createElement("input");t.type="file",t.accept="image/jpeg";const a=()=>{t.files&&t.files[0]&&e(t.files[0])};return t.addEventListener("change",a),{startSelect:()=>{t.click()},destroy:()=>{t.removeEventListener("change",a)}}})(e);return o.exports.useEffect((()=>a)),m.createElement(we,{label:"画像をアップロード",onClick:t})},Ze=()=>{const[e,t]=o.exports.useState(""),[a,l]=o.exports.useState(""),[n,s]=o.exports.useState(null),r=k();return m.createElement("div",{className:"flex justify-center p-10"},m.createElement("div",{className:"flex justify-center w-full max-w-2xl"},m.createElement(K,null,m.createElement("div",{className:"w-full"},m.createElement("h2",{className:"mb-8 text-xl font-bold"},"ISUを登録"),m.createElement("div",{className:"flex flex-col gap-4"},m.createElement(Ne,{label:"JIAのIsuID",value:e,setValue:t}),m.createElement(Ne,{label:"ISUの名前",value:a,setValue:l}),m.createElement("div",{className:"flex flex-col gap-8 items-center mt-6"},m.createElement(Re,{putIsuIcon:s}),m.createElement(H,{label:"登録",onClick:async()=>{try{const t={jia_isu_uuid:e,isu_name:a};n&&(t.image=n),await R.postIsu(t),r.push(`/isu/${e}`)}catch(t){409===t.response.status?r.push(`/isu/${e}`):alert(t.response.data)}},customClass:"px-4 py-1 h-8 text-white-primary font-bold bg-button rounded-2xl",disabled:!e||!a})))))))},Je=()=>m.createElement("div",{className:"flex flex-col min-h-full text-primary"},m.createElement($,null,m.createElement(Y,null),m.createElement("div",{className:"flex-1 bg-primary"},m.createElement(j,null,m.createElement(ge,{path:"/",exact:!0},m.createElement(me,null)),m.createElement(ge,{path:"/isu/:id"},m.createElement(Ve,null)),m.createElement(ge,{path:"/register",exact:!0},m.createElement(Ze,null)),m.createElement(h,null,m.createElement(v,{to:"/"}))))));I.render(m.createElement(o.exports.StrictMode,null,m.createElement(z,null,m.createElement(Je,null))),document.getElementById("root")),d.setAppElement("#root");
diff --git a/webapp/public/index.html b/webapp/public/index.html
index eafe1b779..c6735ce88 100644
--- a/webapp/public/index.html
+++ b/webapp/public/index.html
@@ -5,7 +5,7 @@
     <link rel="icon" type="image/svg+xml" href="/assets/favicon.d0f5f504.svg" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>ISUCONDITION</title>
-  <script type="module" crossorigin src="/assets/index.8fb7127f.js"></script>
+  <script type="module" crossorigin src="/assets/index.62e30cf3.js"></script>
   <link rel="modulepreload" href="/assets/vendor.f1db1b60.js">
   <link rel="stylesheet" href="/assets/index.d5e7f1e4.css">
 </head>


Test patch: