✨ Fix Calendar Drag & Drop Duplicate Events Issue
� Fixed Issues:
- Fixed duplicate events when dragging from sidebar to calendar
- Used info.revert() to prevent FullCalendar auto-adding events
- Manual event management through React state for better control
- Single event display after drag & drop (no more duplicates)
� Features Enhanced:
- Drag & Drop from sidebar to calendar (no duplicates)
- Internal calendar event dragging still works
- Event tracking in 'Recently Dropped Events' section
- Remove after drop option functionality
- Beautiful UI with 4 pre-existing events and 10 draggable events
- Dynamic dates based on current date for better visibility
✨ Technical Improvements:
- Better state management for calendar events
- Clean event handling with proper React patterns
- Console logging for debugging (no alert popups)
- Stable and reliable drag & drop experience
- Professional UX with smooth interactions
� UI/UX:
- Color-coded events with emoji icons
- Responsive calendar layout
- Event tracking with timestamps
- Clean and modern interface
- dayMaxEvents=3 for optimal display
This commit is contained in:
parent
71fd633073
commit
a5d79ad10f
@ -1,11 +1,12 @@
|
|||||||
/* eslint-disable no-dupe-keys */
|
/* eslint-disable no-dupe-keys */
|
||||||
/* eslint-disable no-const-assign */
|
/* eslint-disable no-const-assign */
|
||||||
/* eslint-disable no-unused-vars */
|
/* eslint-disable no-unused-vars */
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
import FullCalendar from "@fullcalendar/react";
|
import FullCalendar from "@fullcalendar/react";
|
||||||
import dayGridPlugin from "@fullcalendar/daygrid";
|
import dayGridPlugin from "@fullcalendar/daygrid";
|
||||||
import timeGridPlugin from "@fullcalendar/timegrid";
|
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||||
import interactionPlugin from "@fullcalendar/interaction";
|
import interactionPlugin from "@fullcalendar/interaction";
|
||||||
|
import { Draggable } from "@fullcalendar/interaction";
|
||||||
// import "../../assets/plugins/fullcalendar/fullcalendar.min.css";
|
// import "../../assets/plugins/fullcalendar/fullcalendar.min.css";
|
||||||
import "../../style/css/fullcalendar.min.css";
|
import "../../style/css/fullcalendar.min.css";
|
||||||
// import FullCalendar from '@fullcalendar/react/dist/main.esm.js';
|
// import FullCalendar from '@fullcalendar/react/dist/main.esm.js';
|
||||||
@ -25,35 +26,102 @@ const Calendar = () => {
|
|||||||
[category_color, setcategory_color] = useState(""),
|
[category_color, setcategory_color] = useState(""),
|
||||||
[calenderevent, setcalenderevent] = useState(""),
|
[calenderevent, setcalenderevent] = useState(""),
|
||||||
[weekendsVisible, setweekendsVisible] = useState(true),
|
[weekendsVisible, setweekendsVisible] = useState(true),
|
||||||
[currentEvents, setscurrentEvents] = useState([]),
|
[currentEvents, setscurrentEvents] = useState([]);
|
||||||
defaultEvents = [
|
|
||||||
{
|
const calendarRef = useRef(null);
|
||||||
title: "Event Name 4",
|
|
||||||
start: Date.now() + 148000000,
|
// State to store dropped events temporarily
|
||||||
className: "bg-purple",
|
const [droppedEvents, setDroppedEvents] = useState([]);
|
||||||
},
|
|
||||||
{
|
// Combined events state for calendar display - using current dates
|
||||||
title: "Test Event 1",
|
const today = new Date();
|
||||||
start: Date.now(),
|
const [calendarEvents, setCalendarEvents] = useState([
|
||||||
end: Date.now(),
|
{
|
||||||
className: "bg-success",
|
id: 'default-1',
|
||||||
},
|
title: "🎯 Existing Meeting",
|
||||||
{
|
start: new Date(today.getFullYear(), today.getMonth(), today.getDate(), 10, 0), // Today 10:00 AM
|
||||||
title: "Test Event 2",
|
end: new Date(today.getFullYear(), today.getMonth(), today.getDate(), 11, 0), // Today 11:00 AM
|
||||||
start: Date.now() + 168000000,
|
className: "bg-primary",
|
||||||
className: "bg-info",
|
},
|
||||||
},
|
{
|
||||||
{
|
id: 'default-2',
|
||||||
title: "Test Event 3",
|
title: "📈 Weekly Review",
|
||||||
start: Date.now() + 338000000,
|
start: new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1, 14, 0), // Tomorrow 2:00 PM
|
||||||
className: "bg-primary",
|
end: new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1, 15, 30), // Tomorrow 3:30 PM
|
||||||
},
|
className: "bg-success",
|
||||||
];
|
},
|
||||||
|
{
|
||||||
|
id: 'default-3',
|
||||||
|
title: "🚀 Product Demo",
|
||||||
|
start: new Date(today.getFullYear(), today.getMonth(), today.getDate() + 2, 9, 0), // Day after tomorrow 9:00 AM
|
||||||
|
end: new Date(today.getFullYear(), today.getMonth(), today.getDate() + 2, 10, 0), // Day after tomorrow 10:00 AM
|
||||||
|
className: "bg-info",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'default-4',
|
||||||
|
title: "🎨 Design Review",
|
||||||
|
start: new Date(today.getFullYear(), today.getMonth(), today.getDate() + 3, 16, 0), // 3 days from now 4:00 PM
|
||||||
|
end: new Date(today.getFullYear(), today.getMonth(), today.getDate() + 3, 17, 0), // 3 days from now 5:00 PM
|
||||||
|
className: "bg-warning",
|
||||||
|
},
|
||||||
|
]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let elements = Array.from(
|
let elements = Array.from(
|
||||||
document.getElementsByClassName("react-datepicker-wrapper")
|
document.getElementsByClassName("react-datepicker-wrapper")
|
||||||
);
|
);
|
||||||
elements.map((element) => element.classList.add("width-100"));
|
elements.map((element) => element.classList.add("width-100"));
|
||||||
|
|
||||||
|
// Initialize external draggable events with simple hide/show
|
||||||
|
const draggableEl = document.getElementById("calendar-events");
|
||||||
|
if (draggableEl) {
|
||||||
|
new Draggable(draggableEl, {
|
||||||
|
itemSelector: ".calendar-events",
|
||||||
|
eventData: function(eventEl) {
|
||||||
|
const title = eventEl.innerText.trim();
|
||||||
|
const className = eventEl.getAttribute("data-class");
|
||||||
|
return {
|
||||||
|
title: title,
|
||||||
|
className: className,
|
||||||
|
duration: "01:00" // 1 hour default duration
|
||||||
|
};
|
||||||
|
},
|
||||||
|
longPressDelay: 0,
|
||||||
|
touchTimeoutDelay: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
// Store reference to currently dragging element
|
||||||
|
let currentDragElement = null;
|
||||||
|
let dragHelper = null;
|
||||||
|
|
||||||
|
// Listen for drag start from external elements
|
||||||
|
draggableEl.addEventListener('dragstart', function(e) {
|
||||||
|
const target = e.target.closest('.calendar-events');
|
||||||
|
if (target) {
|
||||||
|
currentDragElement = target;
|
||||||
|
// Hide the original item when dragging starts
|
||||||
|
setTimeout(() => {
|
||||||
|
if (currentDragElement) {
|
||||||
|
currentDragElement.classList.add('dragging-hidden');
|
||||||
|
}
|
||||||
|
}, 10); // Small delay to let drag start
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Simple approach - just hide the original item during drag
|
||||||
|
// No custom helper, let FullCalendar handle the drag visual
|
||||||
|
|
||||||
|
// Listen for drag end
|
||||||
|
document.addEventListener('dragend', function(e) {
|
||||||
|
if (currentDragElement) {
|
||||||
|
currentDragElement.classList.remove('dragging-hidden');
|
||||||
|
currentDragElement = null;
|
||||||
|
}
|
||||||
|
if (dragHelper && dragHelper.parentNode) {
|
||||||
|
dragHelper.parentNode.removeChild(dragHelper);
|
||||||
|
dragHelper = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleChange = (date) => {
|
const handleChange = (date) => {
|
||||||
@ -85,6 +153,54 @@ const Calendar = () => {
|
|||||||
setisnewevent(true);
|
setisnewevent(true);
|
||||||
setaddneweventobj(selectInfo);
|
setaddneweventobj(selectInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEventReceive = (info) => {
|
||||||
|
// Handle external drag and drop
|
||||||
|
console.log("Event received:", info.event);
|
||||||
|
|
||||||
|
// Prevent FullCalendar from automatically adding the event
|
||||||
|
// We'll handle it manually to avoid duplicates
|
||||||
|
info.revert();
|
||||||
|
|
||||||
|
// Create event object
|
||||||
|
const newEvent = {
|
||||||
|
id: `dropped-${Date.now()}`,
|
||||||
|
title: info.event.title,
|
||||||
|
start: info.event.start,
|
||||||
|
end: info.event.end || new Date(info.event.start.getTime() + 60 * 60 * 1000), // Default 1 hour duration
|
||||||
|
className: info.event.classNames[0] || 'bg-primary',
|
||||||
|
droppedAt: new Date().toLocaleString(),
|
||||||
|
source: 'external'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add to calendar events state to display on calendar
|
||||||
|
setCalendarEvents(prev => [...prev, newEvent]);
|
||||||
|
|
||||||
|
// Add to dropped events list for tracking
|
||||||
|
setDroppedEvents(prev => [...prev, newEvent]);
|
||||||
|
|
||||||
|
// Show success notification in console only
|
||||||
|
console.log("✅ Event successfully dropped:", newEvent);
|
||||||
|
|
||||||
|
// Show the original item again (in case it was hidden)
|
||||||
|
const draggedEl = info.draggedEl;
|
||||||
|
if (draggedEl) {
|
||||||
|
draggedEl.classList.remove('dragging-hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if "Remove after drop" is checked
|
||||||
|
const removeAfterDrop = document.getElementById("drop-remove").checked;
|
||||||
|
if (removeAfterDrop) {
|
||||||
|
// Remove the dragged element from the external list
|
||||||
|
info.draggedEl.remove();
|
||||||
|
console.log("🗑️ Original event removed from sidebar");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEventDrop = (info) => {
|
||||||
|
// Handle internal event drag and drop
|
||||||
|
console.log("Event dropped:", info.event);
|
||||||
|
};
|
||||||
const addnewevent = () => {
|
const addnewevent = () => {
|
||||||
let calendarApi = addneweventobj.view.calendar;
|
let calendarApi = addneweventobj.view.calendar;
|
||||||
|
|
||||||
@ -116,13 +232,13 @@ const Calendar = () => {
|
|||||||
setiseditdelete(false);
|
setiseditdelete(false);
|
||||||
};
|
};
|
||||||
const clickupdateevent = () => {
|
const clickupdateevent = () => {
|
||||||
const newArray = defaultEvents;
|
const newArray = [...calendarEvents];
|
||||||
for (let i = 0; i < newArray.length; i++) {
|
for (let i = 0; i < newArray.length; i++) {
|
||||||
if (newArray[i].id === parseInt(calenderevent.id)) {
|
if (newArray[i].id === parseInt(calenderevent.id)) {
|
||||||
newArray[i].title = event_title;
|
newArray[i].title = event_title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defaultEvents = newArray;
|
setCalendarEvents(newArray);
|
||||||
setiseditdelete(false);
|
setiseditdelete(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -144,17 +260,17 @@ const Calendar = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="page-wrapper">
|
<div className="page-wrapper calendar-page-wrapper">
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<div className="page-header">
|
<div className="calendar-page-header">
|
||||||
<div className="row align-items-center w-100">
|
<div className="row align-items-center w-100">
|
||||||
<div className="col-lg-10 col-sm-12">
|
<div className="col-lg-8 col-sm-12">
|
||||||
<h3 className="page-title">Calendar</h3>
|
<h3 className="page-title">📅 Beautiful Calendar</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-lg-2 col-sm-12">
|
<div className="col-lg-4 col-sm-12 text-end">
|
||||||
<a
|
<a
|
||||||
to="#"
|
href="#"
|
||||||
className="btn btn-primary"
|
className="calendar-create-btn"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#add_event"
|
data-bs-target="#add_event"
|
||||||
>
|
>
|
||||||
@ -165,38 +281,93 @@ const Calendar = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-lg-3 col-md-4">
|
<div className="col-lg-3 col-md-4">
|
||||||
<h4 className="card-title">Drag & Drop Event</h4>
|
<div className="calendar-sidebar">
|
||||||
<div id="calendar-events" className="mb-3">
|
<h4 className="card-title">🎯 Drag & Drop Events</h4>
|
||||||
<div className="calendar-events" data-class="bg-info">
|
<div id="calendar-events" className="mb-3">
|
||||||
<i className="fas fa-circle text-info" /> My Event One
|
<div className="calendar-events" data-class="bg-primary">
|
||||||
|
<i className="fas fa-circle" /> 👥 Team Meeting
|
||||||
|
</div>
|
||||||
|
<div className="calendar-events" data-class="bg-success">
|
||||||
|
<i className="fas fa-circle" /> 📊 Project Review
|
||||||
|
</div>
|
||||||
|
<div className="calendar-events" data-class="bg-warning">
|
||||||
|
<i className="fas fa-circle" /> 📞 Client Call
|
||||||
|
</div>
|
||||||
|
<div className="calendar-events" data-class="bg-danger">
|
||||||
|
<i className="fas fa-circle" /> 🎨 Design Workshop
|
||||||
|
</div>
|
||||||
|
<div className="calendar-events" data-class="bg-info">
|
||||||
|
<i className="fas fa-circle" /> 💻 Code Review
|
||||||
|
</div>
|
||||||
|
<div className="calendar-events" data-class="bg-secondary">
|
||||||
|
<i className="fas fa-circle" /> 🍽️ Lunch Break
|
||||||
|
</div>
|
||||||
|
<div className="calendar-events" data-class="bg-purple">
|
||||||
|
<i className="fas fa-circle" /> 📚 Training Session
|
||||||
|
</div>
|
||||||
|
<div className="calendar-events" data-class="bg-success">
|
||||||
|
<i className="fas fa-circle" /> 🏃 Sprint Planning
|
||||||
|
</div>
|
||||||
|
<div className="calendar-events" data-class="bg-info">
|
||||||
|
<i className="fas fa-circle" /> 🔍 Bug Triage
|
||||||
|
</div>
|
||||||
|
<div className="calendar-events" data-class="bg-warning">
|
||||||
|
<i className="fas fa-circle" /> ☕ Coffee Chat
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="calendar-events" data-class="bg-success">
|
<div className="checkbox mb-3">
|
||||||
<i className="fas fa-circle text-success" /> My Event Two
|
<input id="drop-remove" className="me-1" type="checkbox" />
|
||||||
</div>
|
<label htmlFor="drop-remove">Remove after drop</label>
|
||||||
<div className="calendar-events" data-class="bg-danger">
|
|
||||||
<i className="fas fa-circle text-danger" /> My Event Three
|
|
||||||
</div>
|
|
||||||
<div className="calendar-events" data-class="bg-warning">
|
|
||||||
<i className="fas fa-circle text-warning" /> My Event Four
|
|
||||||
</div>
|
</div>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#add_new_event"
|
||||||
|
className="calendar-add-category-btn"
|
||||||
|
>
|
||||||
|
<i className="fas fa-plus" /> Add Category
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{/* Dropped Events Tracker */}
|
||||||
|
{droppedEvents.length > 0 && (
|
||||||
|
<div className="mt-4">
|
||||||
|
<h5 className="text-success">✅ Recently Dropped Events ({droppedEvents.length})</h5>
|
||||||
|
<div className="dropped-events-list">
|
||||||
|
{droppedEvents.slice(-5).map((event, index) => (
|
||||||
|
<div key={event.id} className="dropped-event-item mb-2 p-2 border rounded">
|
||||||
|
<div className="d-flex justify-content-between align-items-center">
|
||||||
|
<div>
|
||||||
|
<strong>{event.title}</strong>
|
||||||
|
<br />
|
||||||
|
<small className="text-muted">
|
||||||
|
📅 {event.start.toLocaleDateString()} at {event.start.toLocaleTimeString()}
|
||||||
|
</small>
|
||||||
|
<br />
|
||||||
|
<small className="text-success">
|
||||||
|
⏰ Dropped: {event.droppedAt}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<span className={`badge ${event.className}`}>
|
||||||
|
{event.className.replace('bg-', '')}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{droppedEvents.length > 5 && (
|
||||||
|
<small className="text-muted">
|
||||||
|
... and {droppedEvents.length - 5} more events
|
||||||
|
</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="checkbox mb-3">
|
|
||||||
<input id="drop-remove" className="me-1" type="checkbox" />
|
|
||||||
<label htmlFor="drop-remove">Remove after drop</label>
|
|
||||||
</div>
|
|
||||||
<a
|
|
||||||
to="#"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
data-bs-target="#add_new_event"
|
|
||||||
className="btn mb-3 btn-primary btn-block w-100"
|
|
||||||
>
|
|
||||||
<i className="fas fa-plus" /> Add Category
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="col-lg-9 col-md-8">
|
<div className="col-lg-9 col-md-8">
|
||||||
<div className="card bg-white">
|
<div className="calendar-main-card">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<FullCalendar
|
<FullCalendar
|
||||||
|
ref={calendarRef}
|
||||||
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
|
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
|
||||||
headerToolbar={{
|
headerToolbar={{
|
||||||
left: "prev,next today",
|
left: "prev,next today",
|
||||||
@ -207,11 +378,15 @@ const Calendar = () => {
|
|||||||
editable={true}
|
editable={true}
|
||||||
selectable={true}
|
selectable={true}
|
||||||
selectMirror={true}
|
selectMirror={true}
|
||||||
dayMaxEvents={true}
|
dayMaxEvents={3} // Show max 3 events per day, then +more
|
||||||
weekends={weekendsVisible}
|
weekends={weekendsVisible}
|
||||||
initialEvents={defaultEvents} // alternatively, use the `events` setting to fetch from a feed
|
droppable={true} // Enable dropping external events
|
||||||
|
dragScroll={true}
|
||||||
|
events={calendarEvents} // Use dynamic events state
|
||||||
select={handleDateSelect}
|
select={handleDateSelect}
|
||||||
eventClick={(clickInfo) => handleEventClick(clickInfo)}
|
eventClick={(clickInfo) => handleEventClick(clickInfo)}
|
||||||
|
eventReceive={handleEventReceive} // Handle external drops
|
||||||
|
eventDrop={handleEventDrop} // Handle internal drops
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,130 +1,881 @@
|
|||||||
|
/* Beautiful Calendar Styles */
|
||||||
|
|
||||||
|
/* Prevent overflow issues during drag */
|
||||||
|
body.fc-dragging {
|
||||||
|
overflow: visible !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
overflow-x: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable all animations during drag operations */
|
||||||
|
.fc-dragging * {
|
||||||
|
transition: none !important;
|
||||||
|
animation: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* External draggable elements */
|
||||||
|
.fc-draggable-dragging {
|
||||||
|
transition: none !important;
|
||||||
|
animation: none !important;
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calendar Page Layout */
|
||||||
|
.calendar-page-wrapper {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 20px;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
|
||||||
|
.content {
|
||||||
|
background: transparent;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-lg-3, .col-lg-9, .col-md-4, .col-md-8 {
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-page-header {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 25px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-create-btn {
|
||||||
|
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%);
|
||||||
|
border: none;
|
||||||
|
border-radius: 50px;
|
||||||
|
padding: 12px 30px;
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 16px;
|
||||||
|
box-shadow: 0 8px 25px rgba(255, 107, 107, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 12px 35px rgba(255, 107, 107, 0.4);
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "✨";
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calendar Sidebar */
|
||||||
|
.calendar-sidebar {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 25px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
color: #2c3e50;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calendar-events {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calendar Events */
|
||||||
.calendar-events {
|
.calendar-events {
|
||||||
border: 1px solid transparent;
|
background: linear-gradient(135deg, #74b9ff 0%, #0984e3 100%);
|
||||||
cursor: move;
|
color: white;
|
||||||
@include margin-padding(null, 10px 15px);
|
border-radius: 15px;
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
cursor: move;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0 5px 15px rgba(116, 185, 255, 0.3);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: -100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||||
|
transition: left 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(.fc-dragging) {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 8px 25px rgba(116, 185, 255, 0.4);
|
||||||
|
background: linear-gradient(135deg, #0984e3 0%, #74b9ff 100%);
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple drag state - just hide the item completely
|
||||||
|
&.dragging-hidden {
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
transition: none !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.calendar-events:hover {
|
|
||||||
border-color: $gray-300;
|
// Dropped Events Tracker Styling
|
||||||
background-color: $white;
|
.dropped-events-list {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.dropped-event-item {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1) !important;
|
||||||
|
border-radius: 10px !important;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 15px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
&.bg-primary { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; }
|
||||||
|
&.bg-success { background: linear-gradient(135deg, #00b894 0%, #00cec9 100%) !important; }
|
||||||
|
&.bg-warning { background: linear-gradient(135deg, #fdcb6e 0%, #e84393 100%) !important; }
|
||||||
|
&.bg-danger { background: linear-gradient(135deg, #e17055 0%, #d63031 100%) !important; }
|
||||||
|
&.bg-info { background: linear-gradient(135deg, #74b9ff 0%, #0984e3 100%) !important; }
|
||||||
|
&.bg-secondary { background: linear-gradient(135deg, #636e72 0%, #2d3436 100%) !important; }
|
||||||
|
&.bg-purple { background: linear-gradient(135deg, #a29bfe 0%, #6c5ce7 100%) !important; }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.calendar-events i {
|
|
||||||
margin-right: 8px;
|
// Hide dragged items during drag
|
||||||
|
.calendar-events.dragging-hidden {
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
transition: none !important;
|
||||||
|
pointer-events: none !important;
|
||||||
}
|
}
|
||||||
.calendar {
|
|
||||||
float: left;
|
/* Calendar Events - Additional Styles */
|
||||||
margin-bottom: 0;
|
.calendar-events {
|
||||||
|
&[data-class="bg-success"] {
|
||||||
|
background: linear-gradient(135deg, #00b894 0%, #00cec9 100%);
|
||||||
|
box-shadow: 0 5px 15px rgba(0, 184, 148, 0.3);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #00cec9 0%, #00b894 100%);
|
||||||
|
box-shadow: 0 8px 25px rgba(0, 184, 148, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: linear-gradient(135deg, #00a085 0%, #00b8b3 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-class="bg-danger"] {
|
||||||
|
background: linear-gradient(135deg, #e17055 0%, #d63031 100%);
|
||||||
|
box-shadow: 0 5px 15px rgba(225, 112, 85, 0.3);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #d63031 0%, #e17055 100%);
|
||||||
|
box-shadow: 0 8px 25px rgba(225, 112, 85, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: linear-gradient(135deg, #c92a2a 0%, #d63031 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-class="bg-warning"] {
|
||||||
|
background: linear-gradient(135deg, #fdcb6e 0%, #e84393 100%);
|
||||||
|
box-shadow: 0 5px 15px rgba(253, 203, 110, 0.3);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #e84393 0%, #fdcb6e 100%);
|
||||||
|
box-shadow: 0 8px 25px rgba(253, 203, 110, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: linear-gradient(135deg, #d63384 0%, #fab005 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drag states - simplified without problematic animations
|
||||||
|
&.fc-dragging {
|
||||||
|
opacity: 0.8 !important;
|
||||||
|
z-index: 9999 !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3) !important;
|
||||||
|
transition: none !important; // Disable transitions during drag
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dragging state for external events
|
||||||
|
&[data-is-dragging="true"] {
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: none !important; // Disable transitions during drag
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.fc-toolbar.fc-header-toolbar {
|
|
||||||
margin-bottom: 1.5rem;
|
// Let FullCalendar handle drag mirrors naturally
|
||||||
|
.fc-event-dragging,
|
||||||
|
.fc-event-mirror,
|
||||||
|
.fc-draggable-mirror {
|
||||||
|
// Just hide them completely for clean experience
|
||||||
|
display: none !important;
|
||||||
}
|
}
|
||||||
.none-border .modal-footer {
|
|
||||||
border-top: none;
|
// Calendar drop zones
|
||||||
|
.fc-day-grid .fc-day.fc-highlight,
|
||||||
|
.fc-daygrid-day.fc-highlight {
|
||||||
|
background: rgba(102, 126, 234, 0.1) !important;
|
||||||
|
border: 2px dashed rgba(102, 126, 234, 0.5) !important;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '📅 Drop here';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
color: rgba(102, 126, 234, 0.8);
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 12px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.fc-toolbar h2 {
|
|
||||||
font-size: $font-size-18;
|
.fc-time-grid .fc-highlight {
|
||||||
font-weight: $font-weight-semibold;
|
background: rgba(102, 126, 234, 0.1) !important;
|
||||||
font-family: 'Roboto', sans-serif;
|
border: 2px dashed rgba(102, 126, 234, 0.5) !important;
|
||||||
line-height: 30px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
}
|
||||||
.fc-day-grid-event .fc-time {
|
|
||||||
font-family: 'Roboto', sans-serif;
|
/* Add Category Button */
|
||||||
|
.calendar-add-category-btn {
|
||||||
|
background: linear-gradient(135deg, #a29bfe 0%, #6c5ce7 100%);
|
||||||
|
border: none;
|
||||||
|
border-radius: 50px;
|
||||||
|
padding: 15px 25px;
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
width: 100%;
|
||||||
|
box-shadow: 0 8px 25px rgba(162, 155, 254, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 12px 35px rgba(162, 155, 254, 0.4);
|
||||||
|
color: white;
|
||||||
|
background: linear-gradient(135deg, #6c5ce7 0%, #a29bfe 100%);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.fc-day {
|
|
||||||
background: $white;
|
/* Calendar Main Card */
|
||||||
|
.calendar-main-card {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 30px;
|
||||||
|
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.fc-toolbar .fc-state-active,
|
|
||||||
.fc-toolbar .ui-state-active,
|
/* FullCalendar Beautiful Styling */
|
||||||
.fc-toolbar button:focus,
|
.fc {
|
||||||
.fc-toolbar button:hover,
|
font-family: 'Inter', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
.fc-toolbar .ui-state-hover {
|
position: relative;
|
||||||
z-index: 0;
|
overflow: visible;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.fc th.fc-widget-header {
|
|
||||||
background: $gray-300;
|
.fc-toolbar-title {
|
||||||
font-size: $font-size-14;
|
font-size: 2rem !important;
|
||||||
line-height: 20px;
|
font-weight: 700 !important;
|
||||||
padding: 10px 0;
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
text-transform: uppercase;
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 1.5rem !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.fc-unthemed th,
|
|
||||||
.fc-unthemed td,
|
.fc-button-primary {
|
||||||
.fc-unthemed thead,
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
|
||||||
.fc-unthemed tbody,
|
border: none !important;
|
||||||
.fc-unthemed .fc-divider,
|
border-radius: 10px !important;
|
||||||
.fc-unthemed .fc-row,
|
padding: 8px 16px !important;
|
||||||
.fc-unthemed .fc-popover {
|
font-weight: 600 !important;
|
||||||
border-color: #f3f3f3;
|
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3) !important;
|
||||||
|
transition: all 0.3s ease !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px) !important;
|
||||||
|
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4) !important;
|
||||||
|
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:disabled):active,
|
||||||
|
&:not(:disabled).fc-button-active {
|
||||||
|
background: linear-gradient(135deg, #5a4fcf 0%, #667eea 100%) !important;
|
||||||
|
box-shadow: 0 2px 10px rgba(102, 126, 234, 0.5) !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.fc-basic-view .fc-day-number,
|
|
||||||
.fc-basic-view .fc-week-number {
|
.fc-daygrid-day {
|
||||||
padding: 2px 5px;
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(102, 126, 234, 0.05) !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.fc-button {
|
|
||||||
background: #f1f1f1;
|
.fc-day-today {
|
||||||
border: none;
|
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%) !important;
|
||||||
color: #797979;
|
border: 2px solid rgba(102, 126, 234, 0.3) !important;
|
||||||
text-transform: capitalize;
|
position: relative;
|
||||||
box-shadow: none !important;
|
|
||||||
border-radius: 3px !important;
|
&::before {
|
||||||
margin: 0 3px !important;
|
content: '📅';
|
||||||
padding: 6px 12px !important;
|
position: absolute;
|
||||||
height: auto !important;
|
top: 5px;
|
||||||
}
|
right: 5px;
|
||||||
.fc-text-arrow {
|
font-size: 12px;
|
||||||
font-family: inherit;
|
opacity: 0.7;
|
||||||
font-size: $font-size-16;
|
}
|
||||||
}
|
|
||||||
.fc-state-hover {
|
|
||||||
background: #f3f3f3;
|
|
||||||
}
|
|
||||||
.fc-state-highlight {
|
|
||||||
background: #f0f0f0;
|
|
||||||
}
|
|
||||||
.fc-state-down,
|
|
||||||
.fc-state-active,
|
|
||||||
.fc-state-disabled {
|
|
||||||
background-color: $primary !important;
|
|
||||||
color: $white !important;
|
|
||||||
text-shadow: none !important;
|
|
||||||
}
|
|
||||||
.fc-cell-overlay {
|
|
||||||
background: #f0f0f0;
|
|
||||||
}
|
|
||||||
.fc-unthemed .fc-today {
|
|
||||||
background: $white;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.fc-event {
|
.fc-event {
|
||||||
border-radius: 2px;
|
border-radius: 8px !important;
|
||||||
border: none;
|
border: none !important;
|
||||||
color: $white !important;
|
padding: 4px 8px !important;
|
||||||
cursor: move;
|
font-weight: 600 !important;
|
||||||
font-size: 13px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15) !important;
|
||||||
margin: 1px 7px;
|
transition: all 0.3s ease !important;
|
||||||
padding: 5px 5px;
|
position: relative;
|
||||||
text-align: center;
|
overflow: hidden;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: -100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
|
||||||
|
transition: left 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-1px) !important;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2) !important;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bg-purple {
|
||||||
|
background: linear-gradient(135deg, #a29bfe 0%, #6c5ce7 100%) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bg-success {
|
||||||
|
background: linear-gradient(135deg, #00b894 0%, #00cec9 100%) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bg-info {
|
||||||
|
background: linear-gradient(135deg, #74b9ff 0%, #0984e3 100%) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bg-primary {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.fc-basic-view td.fc-week-number span {
|
|
||||||
padding-right: 8px;
|
.fc-daygrid-day-number {
|
||||||
font-weight: $font-weight-bold;
|
font-weight: 600 !important;
|
||||||
font-family: 'Roboto', sans-serif;
|
color: #2c3e50 !important;
|
||||||
|
padding: 8px !important;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #667eea !important;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.fc-basic-view td.fc-day-number {
|
|
||||||
padding-right: 8px;
|
.fc-col-header-cell {
|
||||||
font-weight: $font-weight-bold;
|
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%) !important;
|
||||||
font-family: 'Roboto', sans-serif;
|
font-weight: 700 !important;
|
||||||
|
color: #495057 !important;
|
||||||
|
border: none !important;
|
||||||
|
padding: 15px 8px !important;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
}
|
}
|
||||||
.event-form .input-group .form-control {
|
|
||||||
height: 40px;
|
.fc-scrollgrid {
|
||||||
|
border: none !important;
|
||||||
|
border-radius: 15px !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.submit-section {
|
|
||||||
text-align: center;
|
.fc-theme-standard td,
|
||||||
margin-top: 40px;
|
.fc-theme-standard th {
|
||||||
|
border-color: rgba(0, 0, 0, 0.05) !important;
|
||||||
}
|
}
|
||||||
.submit-btn {
|
|
||||||
|
/* Checkbox Styling */
|
||||||
|
.checkbox {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
accent-color: #667eea;
|
||||||
|
margin-right: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #495057;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modal Enhancements */
|
||||||
|
.modal.custom-modal {
|
||||||
|
.modal-content {
|
||||||
|
border-radius: 20px;
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
border-radius: 20px 20px 0 0;
|
||||||
|
padding: 20px 25px;
|
||||||
|
border-bottom: none;
|
||||||
|
|
||||||
|
.modal-title {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-close {
|
||||||
|
filter: brightness(0) invert(1);
|
||||||
|
opacity: 0.8;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
padding: 25px;
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #2c3e50;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 2px solid #e9ecef;
|
||||||
|
padding: 12px 15px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: #667eea;
|
||||||
|
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-section {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border: none;
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
font-size: $font-size-18;
|
padding: 12px 30px;
|
||||||
font-weight: $font-weight-semibold;
|
color: white;
|
||||||
min-width: 200px;
|
font-weight: 600;
|
||||||
padding: 10px 20px;
|
font-size: 16px;
|
||||||
|
min-width: 150px;
|
||||||
|
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 12px 35px rgba(102, 126, 234, 0.4);
|
||||||
|
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-success {
|
||||||
|
background: linear-gradient(135deg, #00b894 0%, #00cec9 100%);
|
||||||
|
box-shadow: 0 8px 25px rgba(0, 184, 148, 0.3);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #00cec9 0%, #00b894 100%);
|
||||||
|
box-shadow: 0 12px 35px rgba(0, 184, 148, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-danger {
|
||||||
|
background: linear-gradient(135deg, #e17055 0%, #d63031 100%);
|
||||||
|
box-shadow: 0 8px 25px rgba(225, 112, 85, 0.3);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #d63031 0%, #e17055 100%);
|
||||||
|
box-shadow: 0 12px 35px rgba(225, 112, 85, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark Mode Support */
|
||||||
|
[data-layout-mode="dark_mode"] {
|
||||||
|
.calendar-page-wrapper {
|
||||||
|
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-page-header {
|
||||||
|
background: rgba(29, 29, 66, 0.95);
|
||||||
|
border: 1px solid rgba(103, 116, 142, 0.3);
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-sidebar {
|
||||||
|
background: rgba(29, 29, 66, 0.95);
|
||||||
|
border: 1px solid rgba(103, 116, 142, 0.3);
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-main-card {
|
||||||
|
background: rgba(29, 29, 66, 0.95);
|
||||||
|
border: 1px solid rgba(103, 116, 142, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-col-header-cell {
|
||||||
|
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%) !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-daygrid-day-number {
|
||||||
|
color: #ffffff !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #ff9f43 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-day-today {
|
||||||
|
background: linear-gradient(135deg, rgba(255, 159, 67, 0.1) 0%, rgba(254, 202, 87, 0.1) 100%) !important;
|
||||||
|
border: 2px solid rgba(255, 159, 67, 0.3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-toolbar-title {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-button-primary {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%) !important;
|
||||||
|
box-shadow: 0 4px 15px rgba(255, 159, 67, 0.3) !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #feca57 0%, #ff9f43 100%) !important;
|
||||||
|
box-shadow: 0 6px 20px rgba(255, 159, 67, 0.4) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:disabled):active,
|
||||||
|
&:not(:disabled).fc-button-active {
|
||||||
|
background: linear-gradient(135deg, #e8890a 0%, #ff9f43 100%) !important;
|
||||||
|
box-shadow: 0 2px 10px rgba(255, 159, 67, 0.5) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-daygrid-day:hover {
|
||||||
|
background: rgba(255, 159, 67, 0.05) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.custom-modal {
|
||||||
|
.modal-content {
|
||||||
|
background: rgba(29, 29, 66, 0.95);
|
||||||
|
border: 1px solid rgba(103, 116, 142, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
background: rgba(29, 29, 66, 0.95);
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
label {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
background: rgba(29, 29, 66, 0.8);
|
||||||
|
border-color: rgba(103, 116, 142, 0.5);
|
||||||
|
color: #ffffff;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: #ff9f43;
|
||||||
|
box-shadow: 0 0 0 3px rgba(255, 159, 67, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%);
|
||||||
|
box-shadow: 0 8px 25px rgba(255, 159, 67, 0.3);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #feca57 0%, #ff9f43 100%);
|
||||||
|
box-shadow: 0 12px 35px rgba(255, 159, 67, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox label {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dark mode drag & drop
|
||||||
|
.fc-day-grid .fc-day.fc-highlight,
|
||||||
|
.fc-daygrid-day.fc-highlight {
|
||||||
|
background: rgba(255, 159, 67, 0.1) !important;
|
||||||
|
border: 2px dashed rgba(255, 159, 67, 0.5) !important;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
color: rgba(255, 159, 67, 0.8) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-time-grid .fc-highlight {
|
||||||
|
background: rgba(255, 159, 67, 0.1) !important;
|
||||||
|
border: 2px dashed rgba(255, 159, 67, 0.5) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading Animation */
|
||||||
|
@keyframes shimmer {
|
||||||
|
0% {
|
||||||
|
background-position: -468px 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 468px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-loading {
|
||||||
|
background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%);
|
||||||
|
background-size: 800px 104px;
|
||||||
|
animation: shimmer 1.5s infinite linear;
|
||||||
|
border-radius: 15px;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Design */
|
||||||
|
@media (max-width: 992px) {
|
||||||
|
.calendar-sidebar {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.calendar-page-wrapper {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-page-header {
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-sidebar {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-main-card {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-toolbar {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
.fc-toolbar-chunk {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-events {
|
||||||
|
padding: 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
.calendar-page-header h3 {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-create-btn {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-toolbar-title {
|
||||||
|
font-size: 1.3rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-button-primary {
|
||||||
|
padding: 6px 12px !important;
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1434,3 +1434,152 @@ ul.ant-pagination.ant-table-pagination li button.ant-pagination-item-link {
|
|||||||
.section-notes-slider .notes-slider .slick-list .slick-slide div{
|
.section-notes-slider .notes-slider .slick-list .slick-slide div{
|
||||||
margin-left: 12px !important;
|
margin-left: 12px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calendar Dark Mode Integration
|
||||||
|
[data-layout-mode="dark_mode"] {
|
||||||
|
.calendar-page-wrapper {
|
||||||
|
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-page-header {
|
||||||
|
background: rgba(29, 29, 66, 0.95) !important;
|
||||||
|
border: 1px solid rgba(103, 116, 142, 0.3) !important;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%) !important;
|
||||||
|
-webkit-background-clip: text !important;
|
||||||
|
-webkit-text-fill-color: transparent !important;
|
||||||
|
background-clip: text !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-sidebar {
|
||||||
|
background: rgba(29, 29, 66, 0.95) !important;
|
||||||
|
border: 1px solid rgba(103, 116, 142, 0.3) !important;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-main-card {
|
||||||
|
background: rgba(29, 29, 66, 0.95) !important;
|
||||||
|
border: 1px solid rgba(103, 116, 142, 0.3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-col-header-cell {
|
||||||
|
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%) !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-daygrid-day-number {
|
||||||
|
color: #ffffff !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #ff9f43 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-day-today {
|
||||||
|
background: linear-gradient(135deg, rgba(255, 159, 67, 0.1) 0%, rgba(254, 202, 87, 0.1) 100%) !important;
|
||||||
|
border: 2px solid rgba(255, 159, 67, 0.3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-toolbar-title {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%) !important;
|
||||||
|
-webkit-background-clip: text !important;
|
||||||
|
-webkit-text-fill-color: transparent !important;
|
||||||
|
background-clip: text !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-button-primary {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%) !important;
|
||||||
|
box-shadow: 0 4px 15px rgba(255, 159, 67, 0.3) !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #feca57 0%, #ff9f43 100%) !important;
|
||||||
|
box-shadow: 0 6px 20px rgba(255, 159, 67, 0.4) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:disabled):active,
|
||||||
|
&:not(:disabled).fc-button-active {
|
||||||
|
background: linear-gradient(135deg, #e8890a 0%, #ff9f43 100%) !important;
|
||||||
|
box-shadow: 0 2px 10px rgba(255, 159, 67, 0.5) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-daygrid-day:hover {
|
||||||
|
background: rgba(255, 159, 67, 0.05) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-create-btn {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%) !important;
|
||||||
|
box-shadow: 0 8px 25px rgba(255, 159, 67, 0.3) !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #feca57 0%, #ff9f43 100%) !important;
|
||||||
|
box-shadow: 0 12px 35px rgba(255, 159, 67, 0.4) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-add-category-btn {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%) !important;
|
||||||
|
box-shadow: 0 8px 25px rgba(255, 159, 67, 0.3) !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #feca57 0%, #ff9f43 100%) !important;
|
||||||
|
box-shadow: 0 12px 35px rgba(255, 159, 67, 0.4) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calendar Modal Dark Mode
|
||||||
|
.modal.custom-modal {
|
||||||
|
.modal-content {
|
||||||
|
background: rgba(29, 29, 66, 0.95) !important;
|
||||||
|
border: 1px solid rgba(103, 116, 142, 0.3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
background: rgba(29, 29, 66, 0.95) !important;
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
label {
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
background: rgba(29, 29, 66, 0.8) !important;
|
||||||
|
border-color: rgba(103, 116, 142, 0.5) !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: #ff9f43 !important;
|
||||||
|
box-shadow: 0 0 0 3px rgba(255, 159, 67, 0.1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.5) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
background: linear-gradient(135deg, #ff9f43 0%, #feca57 100%) !important;
|
||||||
|
box-shadow: 0 8px 25px rgba(255, 159, 67, 0.3) !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #feca57 0%, #ff9f43 100%) !important;
|
||||||
|
box-shadow: 0 12px 35px rgba(255, 159, 67, 0.4) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox label {
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user