From c60b6fda529541d266fa706e2956102770e78637 Mon Sep 17 00:00:00 2001 From: ckx6954 Date: Thu, 19 Dec 2024 13:31:10 +0900 Subject: [PATCH] =?UTF-8?q?=EB=8B=AC=EB=A0=A5=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=EC=9D=B4=EB=9E=91=20=EB=98=91=EA=B0=99=EC=9D=B4=20?= =?UTF-8?q?=EB=A7=8C=EB=93=AC=20(=EC=A1=B0=EA=B8=88=20=EB=8B=A4=EB=A5=BC?= =?UTF-8?q?=20=EC=88=98=20=EC=9E=88=EC=9D=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 +- package-lock.json | 23 +++ package.json | 2 + public/js/app-calendar.js | 2 +- src/assets/css/app-calendar.css | 1 + src/components/calendar/SampleCalendar.vue | 199 ++++++++++++++++----- src/components/modal/CenterModal.vue | 47 +++++ 7 files changed, 231 insertions(+), 45 deletions(-) create mode 100644 src/assets/css/app-calendar.css create mode 100644 src/components/modal/CenterModal.vue diff --git a/index.html b/index.html index 9b7f844..d00fe61 100644 --- a/index.html +++ b/index.html @@ -45,7 +45,7 @@ - + diff --git a/package-lock.json b/package-lock.json index b4426fa..c2c4262 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,11 +18,13 @@ "axios": "^1.7.9", "bootstrap": "^5.3.3", "dayjs": "^1.11.13", + "flatpickr": "^4.6.13", "front": "file:", "pinia": "^2.2.6", "pinia-plugin-persist": "^1.0.0", "quill": "^2.0.3", "vue": "^3.5.13", + "vue-flatpickr-component": "^11.0.5", "vue-router": "^4.4.5" }, "devDependencies": { @@ -2730,6 +2732,12 @@ "node": ">=16" } }, + "node_modules/flatpickr": { + "version": "4.6.13", + "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", + "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==", + "license": "MIT" + }, "node_modules/flatted": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", @@ -4511,6 +4519,21 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/vue-flatpickr-component": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/vue-flatpickr-component/-/vue-flatpickr-component-11.0.5.tgz", + "integrity": "sha512-Vfwg5uVU+sanKkkLzUGC5BUlWd5wlqAMq/UpQ6lI2BCZq0DDrXhOMX7hrevt8bEgglIq2QUv0K2Nl84Me/VnlA==", + "license": "MIT", + "dependencies": { + "flatpickr": "^4.6.13" + }, + "engines": { + "node": ">=14.13.0" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, "node_modules/vue-router": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.0.tgz", diff --git a/package.json b/package.json index 237a142..f452a1b 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,13 @@ "axios": "^1.7.9", "bootstrap": "^5.3.3", "dayjs": "^1.11.13", + "flatpickr": "^4.6.13", "front": "file:", "pinia": "^2.2.6", "pinia-plugin-persist": "^1.0.0", "quill": "^2.0.3", "vue": "^3.5.13", + "vue-flatpickr-component": "^11.0.5", "vue-router": "^4.4.5" }, "devDependencies": { diff --git a/public/js/app-calendar.js b/public/js/app-calendar.js index aae5651..73c57b4 100644 --- a/public/js/app-calendar.js +++ b/public/js/app-calendar.js @@ -1 +1 @@ -let direction="ltr";isRtl&&(direction="rtl"),document.addEventListener("DOMContentLoaded",function(){{let e=document.getElementById("calendar"),t=document.querySelector(".app-calendar-sidebar"),n=document.getElementById("addEventSidebar"),a=document.querySelector(".app-overlay"),l={Business:"primary",Holiday:"success",Personal:"danger",Family:"warning",ETC:"info"},r=document.querySelector(".offcanvas-title"),i=document.querySelector(".btn-toggle-sidebar"),d=document.querySelector("#addEventBtn"),o=document.querySelector(".btn-delete-event"),s=document.querySelector(".btn-cancel"),c=document.querySelector("#eventTitle"),u=document.querySelector("#eventStartDate"),v=document.querySelector("#eventEndDate"),m=document.querySelector("#eventURL"),p=$("#eventLabel"),f=$("#eventGuests"),g=document.querySelector("#eventLocation"),h=document.querySelector("#eventDescription"),b=document.querySelector(".allDay-switch"),y=document.querySelector(".select-all"),S=[].slice.call(document.querySelectorAll(".input-filter")),L=document.querySelector(".inline-calendar"),E,k=events,w=!1,x,q=new bootstrap.Offcanvas(n);function P(e){return e.id?" "+e.text:e.text}function M(e){return e.id?"
avatar
"+e.text+"
":e.text}var T,A;function F(){var e=document.querySelector(".fc-sidebarToggle-button");for(e.classList.remove("fc-button-primary"),e.classList.add("d-lg-none","d-inline-block","ps-0");e.firstChild;)e.firstChild.remove();e.setAttribute("data-bs-toggle","sidebar"),e.setAttribute("data-overlay",""),e.setAttribute("data-target","#app-calendar-sidebar"),e.insertAdjacentHTML("beforeend",'')}p.length&&p.wrap('
').select2({placeholder:"Select value",dropdownParent:p.parent(),templateResult:P,templateSelection:P,minimumResultsForSearch:-1,escapeMarkup:function(e){return e}}),f.length&&f.wrap('
').select2({placeholder:"Select value",dropdownParent:f.parent(),closeOnSelect:!1,templateResult:M,templateSelection:M,escapeMarkup:function(e){return e}}),u&&(T=u.flatpickr({enableTime:!0,altFormat:"Y-m-dTH:i:S",onReady:function(e,t,n){n.isMobile&&n.mobileInput.setAttribute("step",null)}})),v&&(A=v.flatpickr({enableTime:!0,altFormat:"Y-m-dTH:i:S",onReady:function(e,t,n){n.isMobile&&n.mobileInput.setAttribute("step",null)}})),L&&(x=L.flatpickr({monthSelectorType:"static",inline:!0}));let D=new Calendar(e,{initialView:"dayGridMonth",events:function(e,t){let n=function(){let t=[],e=[].slice.call(document.querySelectorAll(".input-filter:checked"));return e.forEach(e=>{t.push(e.getAttribute("data-value"))}),t}();t(k.filter(function(e){return n.includes(e.extendedProps.calendar.toLowerCase())}))},plugins:[dayGridPlugin,interactionPlugin,listPlugin,timegridPlugin],editable:!0,dragScroll:!0,dayMaxEvents:2,eventResizableFromStart:!0,customButtons:{sidebarToggle:{text:"Sidebar"}},headerToolbar:{start:"sidebarToggle, prev,next, title",end:"dayGridMonth,timeGridWeek,timeGridDay,listMonth"},direction:direction,initialDate:new Date,navLinks:!0,eventClassNames:function({event:e}){return["fc-event-"+l[e._def.extendedProps.calendar]]},dateClick:function(e){e=moment(e.date).format("YYYY-MM-DD");C(),q.show(),r&&(r.innerHTML="Add Event"),d.innerHTML="Add",d.classList.remove("btn-update-event"),d.classList.add("btn-add-event"),o.classList.add("d-none"),u.value=e,v.value=e},eventClick:function(e){e=e,(E=e.event).url&&(e.jsEvent.preventDefault(),window.open(E.url,"_blank")),q.show(),r&&(r.innerHTML="Update Event"),d.innerHTML="Update",d.classList.add("btn-update-event"),d.classList.remove("btn-add-event"),o.classList.remove("d-none"),c.value=E.title,T.setDate(E.start,!0,"Y-m-d"),!0===E.allDay?b.checked=!0:b.checked=!1,null!==E.end?A.setDate(E.end,!0,"Y-m-d"):A.setDate(E.start,!0,"Y-m-d"),p.val(E.extendedProps.calendar).trigger("change"),void 0!==E.extendedProps.location&&(g.value=E.extendedProps.location),void 0!==E.extendedProps.guests&&f.val(E.extendedProps.guests).trigger("change"),void 0!==E.extendedProps.description&&(h.value=E.extendedProps.description)},datesSet:function(){F()},viewDidMount:function(){F()}});D.render(),F();var Y=document.getElementById("eventForm");function C(){v.value="",m.value="",u.value="",c.value="",g.value="",b.checked=!1,f.val("").trigger("change"),h.value=""}FormValidation.formValidation(Y,{fields:{eventTitle:{validators:{notEmpty:{message:"Please enter event title "}}},eventStartDate:{validators:{notEmpty:{message:"Please enter start date "}}},eventEndDate:{validators:{notEmpty:{message:"Please enter end date "}}}},plugins:{trigger:new FormValidation.plugins.Trigger,bootstrap5:new FormValidation.plugins.Bootstrap5({eleValidClass:"",rowSelector:function(e,t){return".mb-6"}}),submitButton:new FormValidation.plugins.SubmitButton,autoFocus:new FormValidation.plugins.AutoFocus}}).on("core.form.valid",function(){w=!0}).on("core.form.invalid",function(){w=!1}),i&&i.addEventListener("click",e=>{s.classList.remove("d-none")}),d.addEventListener("click",e=>{var t,n;d.classList.contains("btn-add-event")?w&&(n={id:D.getEvents().length+1,title:c.value,start:u.value,end:v.value,startStr:u.value,endStr:v.value,display:"block",extendedProps:{location:g.value,guests:f.val(),calendar:p.val(),description:h.value}},m.value&&(n.url=m.value),b.checked&&(n.allDay=!0),n=n,k.push(n),D.refetchEvents(),q.hide()):w&&(n={id:E.id,title:c.value,start:u.value,end:v.value,url:m.value,extendedProps:{location:g.value,guests:f.val(),calendar:p.val(),description:h.value},display:"block",allDay:!!b.checked},(t=n).id=parseInt(t.id),k[k.findIndex(e=>e.id===t.id)]=t,D.refetchEvents(),q.hide())}),o.addEventListener("click",e=>{var t;t=parseInt(E.id),k=k.filter(function(e){return e.id!=t}),D.refetchEvents(),q.hide()}),n.addEventListener("hidden.bs.offcanvas",function(){C()}),i.addEventListener("click",e=>{r&&(r.innerHTML="Add Event"),d.innerHTML="Add",d.classList.remove("btn-update-event"),d.classList.add("btn-add-event"),o.classList.add("d-none"),t.classList.remove("show"),a.classList.remove("show")}),y&&y.addEventListener("click",e=>{e.currentTarget.checked?document.querySelectorAll(".input-filter").forEach(e=>e.checked=1):document.querySelectorAll(".input-filter").forEach(e=>e.checked=0),D.refetchEvents()}),S&&S.forEach(e=>{e.addEventListener("click",()=>{document.querySelectorAll(".input-filter:checked").length " + e.text : e.text } function M(e) { return e.id ? "
avatar
" + e.text + "
" : e.text } var T, A; function F() { var e = document.querySelector(".fc-sidebarToggle-button"); for (e.classList.remove("fc-button-primary"), e.classList.add("d-lg-none", "d-inline-block", "ps-0"); e.firstChild;)e.firstChild.remove(); e.setAttribute("data-bs-toggle", "sidebar"), e.setAttribute("data-overlay", ""), e.setAttribute("data-target", "#app-calendar-sidebar"), e.insertAdjacentHTML("beforeend", '') } p.length && p.wrap('
').select2({ placeholder: "Select value", dropdownParent: p.parent(), templateResult: P, templateSelection: P, minimumResultsForSearch: -1, escapeMarkup: function (e) { return e } }), f.length && f.wrap('
').select2({ placeholder: "Select value", dropdownParent: f.parent(), closeOnSelect: !1, templateResult: M, templateSelection: M, escapeMarkup: function (e) { return e } }), u && (T = u.flatpickr({ enableTime: !0, altFormat: "Y-m-dTH:i:S", onReady: function (e, t, n) { n.isMobile && n.mobileInput.setAttribute("step", null) } })), v && (A = v.flatpickr({ enableTime: !0, altFormat: "Y-m-dTH:i:S", onReady: function (e, t, n) { n.isMobile && n.mobileInput.setAttribute("step", null) } })), L && (x = L.flatpickr({ monthSelectorType: "static", inline: !0 })); let D = new Calendar(e, { initialView: "dayGridMonth", events: function (e, t) { let n = function () { let t = [], e = [].slice.call(document.querySelectorAll(".input-filter:checked")); return e.forEach(e => { t.push(e.getAttribute("data-value")) }), t }(); t(k.filter(function (e) { return n.includes(e.extendedProps.calendar.toLowerCase()) })) }, plugins: [dayGridPlugin, interactionPlugin, listPlugin, timegridPlugin], editable: !0, dragScroll: !0, dayMaxEvents: 2, eventResizableFromStart: !0, customButtons: { sidebarToggle: { text: "Sidebar" } }, headerToolbar: { start: "sidebarToggle, prev,next, title", end: "dayGridMonth,timeGridWeek,timeGridDay,listMonth" }, direction: direction, initialDate: new Date, navLinks: !0, eventClassNames: function ({ event: e }) { return ["fc-event-" + l[e._def.extendedProps.calendar]] }, dateClick: function (e) { e = moment(e.date).format("YYYY-MM-DD"); C(), q.show(), r && (r.innerHTML = "Add Event"), d.innerHTML = "Add", d.classList.remove("btn-update-event"), d.classList.add("btn-add-event"), o.classList.add("d-none"), u.value = e, v.value = e }, eventClick: function (e) { e = e, (E = e.event).url && (e.jsEvent.preventDefault(), window.open(E.url, "_blank")), q.show(), r && (r.innerHTML = "Update Event"), d.innerHTML = "Update", d.classList.add("btn-update-event"), d.classList.remove("btn-add-event"), o.classList.remove("d-none"), c.value = E.title, T.setDate(E.start, !0, "Y-m-d"), !0 === E.allDay ? b.checked = !0 : b.checked = !1, null !== E.end ? A.setDate(E.end, !0, "Y-m-d") : A.setDate(E.start, !0, "Y-m-d"), p.val(E.extendedProps.calendar).trigger("change"), void 0 !== E.extendedProps.location && (g.value = E.extendedProps.location), void 0 !== E.extendedProps.guests && f.val(E.extendedProps.guests).trigger("change"), void 0 !== E.extendedProps.description && (h.value = E.extendedProps.description) }, datesSet: function () { F() }, viewDidMount: function () { F() } }); D.render(), F(); var Y = document.getElementById("eventForm"); function C() { v.value = "", m.value = "", u.value = "", c.value = "", g.value = "", b.checked = !1, f.val("").trigger("change"), h.value = "" } FormValidation.formValidation(Y, { fields: { eventTitle: { validators: { notEmpty: { message: "Please enter event title " } } }, eventStartDate: { validators: { notEmpty: { message: "Please enter start date " } } }, eventEndDate: { validators: { notEmpty: { message: "Please enter end date " } } } }, plugins: { trigger: new FormValidation.plugins.Trigger, bootstrap5: new FormValidation.plugins.Bootstrap5({ eleValidClass: "", rowSelector: function (e, t) { return ".mb-6" } }), submitButton: new FormValidation.plugins.SubmitButton, autoFocus: new FormValidation.plugins.AutoFocus } }).on("core.form.valid", function () { w = !0 }).on("core.form.invalid", function () { w = !1 }), i && i.addEventListener("click", e => { s.classList.remove("d-none") }), d.addEventListener("click", e => { var t, n; d.classList.contains("btn-add-event") ? w && (n = { id: D.getEvents().length + 1, title: c.value, start: u.value, end: v.value, startStr: u.value, endStr: v.value, display: "block", extendedProps: { location: g.value, guests: f.val(), calendar: p.val(), description: h.value } }, m.value && (n.url = m.value), b.checked && (n.allDay = !0), n = n, k.push(n), D.refetchEvents(), q.hide()) : w && (n = { id: E.id, title: c.value, start: u.value, end: v.value, url: m.value, extendedProps: { location: g.value, guests: f.val(), calendar: p.val(), description: h.value }, display: "block", allDay: !!b.checked }, (t = n).id = parseInt(t.id), k[k.findIndex(e => e.id === t.id)] = t, D.refetchEvents(), q.hide()) }), o.addEventListener("click", e => { var t; t = parseInt(E.id), k = k.filter(function (e) { return e.id != t }), D.refetchEvents(), q.hide() }), n.addEventListener("hidden.bs.offcanvas", function () { C() }), i.addEventListener("click", e => { r && (r.innerHTML = "Add Event"), d.innerHTML = "Add", d.classList.remove("btn-update-event"), d.classList.add("btn-add-event"), o.classList.add("d-none"), t.classList.remove("show"), a.classList.remove("show") }), y && y.addEventListener("click", e => { e.currentTarget.checked ? document.querySelectorAll(".input-filter").forEach(e => e.checked = 1) : document.querySelectorAll(".input-filter").forEach(e => e.checked = 0), D.refetchEvents() }), S && S.forEach(e => { e.addEventListener("click", () => { document.querySelectorAll(".input-filter:checked").length < document.querySelectorAll(".input-filter").length ? y.checked = !1 : y.checked = !0, D.refetchEvents() }) }), x.config.onChange.push(function (e) { D.changeView(D.view.type, moment(e[0]).format("YYYY-MM-DD")), F(), t.classList.remove("show"), a.classList.remove("show") }) } }); diff --git a/src/assets/css/app-calendar.css b/src/assets/css/app-calendar.css new file mode 100644 index 0000000..fd733bb --- /dev/null +++ b/src/assets/css/app-calendar.css @@ -0,0 +1 @@ +.app-calendar-wrapper{position:relative;border-radius:.375rem}.app-calendar-wrapper .app-calendar-sidebar{position:absolute;overflow:hidden;flex-grow:0;flex-basis:18.75rem;left:calc(-18.75rem - 1.2rem);height:100%;width:18.75rem;transition:all .2s;z-index:4}.app-calendar-wrapper .app-calendar-sidebar.show{left:0}.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar{box-shadow:none}.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-month,.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-weekday,.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-weekdays{background:rgba(0,0,0,0)}.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-days{border:0}.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar:focus{outline:0}.app-calendar-wrapper .app-calendar-content{position:relative}.app-calendar-wrapper .fc-toolbar h2{font-size:1.5rem;line-height:2.375rem}@media(max-width: 767.98px){.app-calendar-wrapper .fc-toolbar h2{font-size:1rem}}.app-calendar-wrapper .fc-toolbar-chunk{overflow:auto}.app-calendar-wrapper table.fc-scrollgrid{border-left:0;border-right:0}.app-calendar-wrapper table.fc-scrollgrid th,.app-calendar-wrapper table.fc-scrollgrid td{border-right:0}.app-calendar-wrapper .fc-timeGridDay-view table.fc-scrollgrid tbody tr:not(.fc-scrollgrid-section:first-of-type) td,.app-calendar-wrapper .fc-timeGridWeek-view table.fc-scrollgrid tbody tr:not(.fc-scrollgrid-section:first-of-type) td{border-bottom:0}.app-calendar-wrapper .fc-dayGridMonth-view table.fc-scrollgrid td{border-bottom:0 !important}.app-calendar-wrapper .fc-header-toolbar{margin-bottom:1.5rem !important}.app-calendar-wrapper .fc-view-container{margin:0 -1.6rem}.app-calendar-wrapper .event-sidebar .ql-editor{min-height:5rem}.app-calendar-wrapper .event-sidebar .select2 .select2-selection__choice{display:flex}.app-calendar-wrapper .event-sidebar .select2 .select2-selection__choice .avatar{display:none}@media(min-width: 992px){.app-calendar-wrapper .app-calendar-sidebar{position:static;height:auto;background-color:rgba(0,0,0,0) !important}.app-calendar-wrapper .app-calendar-sidebar .flatpickr-days{background-color:rgba(0,0,0,0)}}[dir=rtl] .app-calendar-wrapper .fc .fc-toolbar .fc-sidebarToggle-button{order:1}[dir=rtl] .app-calendar-wrapper .app-calendar-sidebar{left:auto;right:calc(-18.75rem - 1.2rem)}[dir=rtl] .app-calendar-wrapper .app-calendar-sidebar.show{left:auto;right:0}.light-style .app-calendar-wrapper .app-calendar-sidebar{background-color:#fff}.dark-style .app-calendar-wrapper .app-calendar-sidebar{background-color:#2b2c40} diff --git a/src/components/calendar/SampleCalendar.vue b/src/components/calendar/SampleCalendar.vue index 33d2198..1fefadc 100644 --- a/src/components/calendar/SampleCalendar.vue +++ b/src/components/calendar/SampleCalendar.vue @@ -1,25 +1,91 @@ diff --git a/src/components/modal/CenterModal.vue b/src/components/modal/CenterModal.vue new file mode 100644 index 0000000..57fb2ec --- /dev/null +++ b/src/components/modal/CenterModal.vue @@ -0,0 +1,47 @@ + + + + + + + + + +