mirror of
https://github.com/TurTaskProject/TurTaskWeb.git
synced 2025-12-19 05:54:07 +01:00
Fetch event data from api and show on fullcalendar
This commit is contained in:
parent
a403e45f9f
commit
02e76f88c5
@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@fullcalendar/core": "^6.1.9",
|
||||
"@fullcalendar/daygrid": "^6.1.9",
|
||||
"@fullcalendar/interaction": "^6.1.9",
|
||||
"@fullcalendar/react": "^6.1.9",
|
||||
|
||||
@ -11,6 +11,9 @@ dependencies:
|
||||
'@emotion/styled':
|
||||
specifier: ^11.11.0
|
||||
version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0)
|
||||
'@fullcalendar/core':
|
||||
specifier: ^6.1.9
|
||||
version: 6.1.9
|
||||
'@fullcalendar/daygrid':
|
||||
specifier: ^6.1.9
|
||||
version: 6.1.9(@fullcalendar/core@6.1.9)
|
||||
|
||||
@ -6,7 +6,8 @@ import LoginPage from './components/authentication/LoginPage';
|
||||
import SignUpPage from './components/authentication/SignUpPage';
|
||||
import NavBar from './components/Nav/Navbar';
|
||||
import Home from './components/Home';
|
||||
import ProfileUpdate from './components/ProfileUpdatePage'
|
||||
import ProfileUpdate from './components/ProfileUpdatePage';
|
||||
import Calendar from './components/calendar/calendar';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
@ -19,6 +20,7 @@ const App = () => {
|
||||
<Route path="/signup" element={<SignUpPage/>}/>
|
||||
<Route path="/testAuth" element={<TestAuth/>}/>
|
||||
<Route path="/update_profile" element={<ProfileUpdate/>}/>
|
||||
<Route path="/calendar" element={<Calendar/>}/>
|
||||
</Routes>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
|
||||
23
frontend/src/api/TaskApi.jsx
Normal file
23
frontend/src/api/TaskApi.jsx
Normal file
@ -0,0 +1,23 @@
|
||||
import axios from 'axios';
|
||||
|
||||
// Create an Axios instance with common configurations
|
||||
const axiosInstance = axios.create({
|
||||
baseURL: 'http://127.0.0.1:8000/api/',
|
||||
timeout: 5000,
|
||||
headers: {
|
||||
'Authorization': "Bearer " + localStorage.getItem('access_token'),
|
||||
'Content-Type': 'application/json',
|
||||
'accept': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
export const fetchTodoTasks = () => {
|
||||
return axiosInstance
|
||||
.get('todo/')
|
||||
.then((response) => {
|
||||
return response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
42
frontend/src/components/calendar/TaskDataHandler.jsx
Normal file
42
frontend/src/components/calendar/TaskDataHandler.jsx
Normal file
@ -0,0 +1,42 @@
|
||||
import { fetchTodoTasks } from '../../api/TaskApi';
|
||||
|
||||
let eventGuid = 0
|
||||
|
||||
// function getDateAndTime(dateString) {
|
||||
// const dateObject = new Date(dateString);
|
||||
|
||||
// const year = dateObject.getFullYear();
|
||||
// const month = (dateObject.getMonth() + 1).toString().padStart(2, '0');
|
||||
// const day = dateObject.getDate().toString().padStart(2, '0');
|
||||
// const dateFormatted = `${year}-${month}-${day}`;
|
||||
|
||||
// const hours = dateObject.getUTCHours().toString().padStart(2, '0');
|
||||
// const minutes = dateObject.getUTCMinutes().toString().padStart(2, '0');
|
||||
// const seconds = dateObject.getUTCSeconds().toString().padStart(2, '0');
|
||||
// const timeFormatted = `T${hours}:${minutes}:${seconds}`;
|
||||
|
||||
// return dateFormatted + timeFormatted;
|
||||
// }
|
||||
|
||||
const mapResponseToEvents = (response) => {
|
||||
return response.map(item => ({
|
||||
id: createEventId(),
|
||||
title: item.title,
|
||||
start: item.start_event,
|
||||
end: item.end_event,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function getEvents() {
|
||||
try {
|
||||
const response = await fetchTodoTasks();
|
||||
return mapResponseToEvents(response);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function createEventId() {
|
||||
return String(eventGuid++);
|
||||
}
|
||||
@ -1,28 +1,127 @@
|
||||
import React from 'react';
|
||||
import FullCalendar from '@fullcalendar/react';
|
||||
import dayGridPlugin from '@fullcalendar/daygrid';
|
||||
import timeGridPlugin from '@fullcalendar/timegrid';
|
||||
import React, { useState } from 'react';
|
||||
import { formatDate } from "@fullcalendar/core";
|
||||
import FullCalendar from "@fullcalendar/react";
|
||||
import dayGridPlugin from "@fullcalendar/daygrid";
|
||||
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||
import interactionPlugin from "@fullcalendar/interaction";
|
||||
import { getEvents, createEventId } from "./TaskDataHandler";
|
||||
import './index.css'
|
||||
|
||||
const Calendar = () => {
|
||||
return (
|
||||
<div className="App">
|
||||
<FullCalendar
|
||||
plugins={[dayGridPlugin, timeGridPlugin]}
|
||||
initialView="dayGridMonth"
|
||||
events={[
|
||||
{ title: 'Event 1', date: '2023-11-10' },
|
||||
{ title: 'Event 2', date: '2023-11-15' },
|
||||
{ title: 'Event 2', date: '2023-11-15' },
|
||||
]}
|
||||
headerToolbar={{
|
||||
start: 'prev,next',
|
||||
center: "title",
|
||||
end: 'timeGridDay,dayGridMonth,timeGridWeek,',
|
||||
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
export default class Calendar extends React.Component {
|
||||
state = {
|
||||
weekendsVisible: true,
|
||||
currentEvents: [],
|
||||
};
|
||||
|
||||
export default Calendar;
|
||||
render() {
|
||||
return (
|
||||
<div className="demo-app">
|
||||
{this.renderSidebar()}
|
||||
<div className="demo-app-main">
|
||||
<FullCalendar
|
||||
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
|
||||
headerToolbar={{
|
||||
left: "prev,next today",
|
||||
center: "title",
|
||||
right: "dayGridMonth,timeGridWeek,timeGridDay",
|
||||
}}
|
||||
initialView="dayGridMonth"
|
||||
editable={true}
|
||||
selectable={true}
|
||||
selectMirror={true}
|
||||
dayMaxEvents={true}
|
||||
weekends={this.state.weekendsVisible}
|
||||
initialEvents={getEvents} // alternatively, use the `events` setting to fetch from a feed
|
||||
select={this.handleDateSelect}
|
||||
eventContent={renderEventContent} // custom render function
|
||||
eventClick={this.handleEventClick}
|
||||
eventsSet={this.handleEvents} // called after events are initialized/added/changed/removed
|
||||
/* you can update a remote database when these fire:
|
||||
eventAdd={function(){}}
|
||||
eventChange={function(){}}
|
||||
eventRemove={function(){}}
|
||||
*/
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderSidebar() {
|
||||
return (
|
||||
<div className="demo-app-sidebar">
|
||||
<div className="demo-app-sidebar-section">
|
||||
<h2>Instructions</h2>
|
||||
<ul>
|
||||
<li>Select dates and you will be prompted to create a new event</li>
|
||||
<li>Drag, drop, and resize events</li>
|
||||
<li>Click an event to delete it</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="demo-app-sidebar-section">
|
||||
<label>
|
||||
<input type="checkbox" checked={this.state.weekendsVisible} onChange={this.handleWeekendsToggle}></input>
|
||||
toggle weekends
|
||||
</label>
|
||||
</div>
|
||||
<div className="demo-app-sidebar-section">
|
||||
<h2>All Events ({this.state.currentEvents.length})</h2>
|
||||
<ul>{this.state.currentEvents.map(renderSidebarEvent)}</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
handleWeekendsToggle = () => {
|
||||
this.setState({
|
||||
weekendsVisible: !this.state.weekendsVisible,
|
||||
});
|
||||
};
|
||||
|
||||
handleDateSelect = selectInfo => {
|
||||
let title = prompt("Please enter a new title for your event");
|
||||
let calendarApi = selectInfo.view.calendar;
|
||||
|
||||
calendarApi.unselect(); // clear date selection
|
||||
|
||||
if (title) {
|
||||
calendarApi.addEvent({
|
||||
id: createEventId(),
|
||||
title,
|
||||
start: selectInfo.startStr,
|
||||
end: selectInfo.endStr,
|
||||
allDay: selectInfo.allDay,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleEventClick = clickInfo => {
|
||||
if (confirm(`Are you sure you want to delete the event '${clickInfo.event.title}'`)) {
|
||||
clickInfo.event.remove();
|
||||
}
|
||||
};
|
||||
|
||||
handleEvents = events => {
|
||||
this.setState({
|
||||
currentEvents: events,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function renderEventContent(eventInfo) {
|
||||
return (
|
||||
<>
|
||||
<b>{eventInfo.timeText}</b>
|
||||
<i>{eventInfo.event.title}</i>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function renderSidebarEvent(event) {
|
||||
return (
|
||||
<li key={event.id}>
|
||||
<b>{formatDate(event.start, { year: "numeric", month: "short", day: "numeric" })}</b>
|
||||
<i>{event.title}</i>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
import React from 'react'
|
||||
|
||||
function calendarPage() {
|
||||
return (
|
||||
<div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default calendarPage
|
||||
55
frontend/src/components/calendar/index.css
Normal file
55
frontend/src/components/calendar/index.css
Normal file
@ -0,0 +1,55 @@
|
||||
|
||||
html,
|
||||
body,
|
||||
body > div { /* the react root */
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 1.5em;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 1.5em 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
b { /* used for event dates/times */
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.demo-app {
|
||||
display: flex;
|
||||
min-height: 100%;
|
||||
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.demo-app-sidebar {
|
||||
width: 300px;
|
||||
line-height: 1.5;
|
||||
background: #eaf9ff;
|
||||
border-right: 1px solid #d3e2e8;
|
||||
}
|
||||
|
||||
.demo-app-sidebar-section {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.demo-app-main {
|
||||
flex-grow: 1;
|
||||
padding: 3em;
|
||||
}
|
||||
|
||||
.fc { /* the calendar root */
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user