Я пытаюсь создать свой собственный компонент еженедельного календаря, используя React и Luxon.
Мой компонент реакции отображает таблицу HTML, каждая ячейка представляет день и время в дне.
Я успешно создал события по щелчку td, используя его идентификатор, событие создает дочерний компонент Event в td.
Однако у меня возникают проблемы при попытке расширить мой компонент Event, чтобы он занимал дополнительные строки.
1) Мне не удалось реализовать успешную функцию изменения размера компонента Event. Я использовал свойство «resize: vertical» css, но когда я отпускаю щелчок, он возвращается к своему первоначальному размеру.
2) Я до сих пор не знаю, будет ли это правильный подход, поскольку я не знаю, есть ли способ, которым я могу сказать реагировать, что мой измененный компонент теперь занимает 2+ строки.
3) Мне интересно, возможно ли расширить дочерний компонент над другой строкой и настроить его на полную высоту новая строка.
Это мой (очень незаконченный) компонент (я также использую Bulma для CSS)
import React, { useState } from 'react'
import { DateTime, Duration } from 'luxon'
function Calendar() {
const startTime = Duration.fromObject({ hours: 8 })
const endTime = Duration.fromObject({ hours: 20 })
const start = DateTime.local().startOf('day').plus(startTime)
const end = DateTime.local().startOf('day').plus(endTime)
const dur = Duration.fromObject({ minutes: 15 })
const range = end.diff(start, ['hours']).hours
const today = DateTime.local()
// const [cellData, setcellData] = useState()
const [activeWeek, setactiveWeek] = useState(today.startOf('week'))
const [events, setevents] = useState({})
const [month, setmonth] = useState(activeWeek.toLocaleString({ month: 'long', }))
// const testTime = DateTime.fromMillis(1586438100000)
// const testDay = DateTime.fromMillis(1586232000000)
// console.log('time', testTime.c.hour)
// console.log('day', testDay.plus({ hours: testTime.c.hour, minutes: testTime.c.minute }).toLocaleString(DateTime.DATETIME_FULL))
const getTimeSlots = (start, dur, range) => {
let slotRange = range * 4
let arr = []
for (let i = 0; i <= slotRange; i++) {
arr = [...arr, {
formatted: start.toLocaleString(DateTime.TIME_24_SIMPLE),
date: start
}]
start = start.plus(dur)
}
return arr
}
const getWeekDays = () => {
let arr = []
for (let i = 0; i < 7; i++) {
let dayOfWeek = activeWeek.plus({ days: i })
let dayDisplayFormat = {
letters: dayOfWeek.toFormat('EEE'),
number: dayOfWeek.toFormat('dd')
}
arr = [...arr, {
formatted: dayDisplayFormat,
date: dayOfWeek
}]
}
return arr
}
const weekDays = getWeekDays()
const timeSlots = getTimeSlots(start, dur, range)
// console.log(timeSlots)
const handleEntryCreation = (e) => {
setevents({
...events,
[e.target.id]: {
date: DateTime.fromFormat(e.target.id, 'EEE dd')
}
})
console.log(events)
}
const calculateSlotDate = (day, time) => {
const slotDate = day.plus({ hours: time.c.hour, minutes: time.c.minute })
return slotDate
}
const handleWeekChange = (action) => {
action === 'forward' ?
setactiveWeek(activeWeek.plus({ week: 1 })) :
setactiveWeek(activeWeek.minus({ week: 1 }))
setmonth(activeWeek.toLocaleString({ month: 'long', }))
}
const Box = () => {
return (
<div className="calendarbox-container">
<div className="calendarbox">
</div>
</div>
)
}
return (
<div className="calendar">
<h1 className="title calendar-title">{month}</h1>
< table className="table is-bordered is-fullwidth" >
<thead>
<tr>
<th onClick={() => handleWeekChange('back')}>{'<'}</th>
{weekDays.map((day) => (
<th key={day.date.ts}>
{day.formatted.letters}
<br />
<span className={
today.hasSame(day.date, 'day') ?
'calendar-today' :
'calendar-notToday'
}>{day.formatted.number}</span>
</th>
))}
<th onClick={() => handleWeekChange('forward')}>{'>'}</th>
</tr>
</thead>
<tbody>
{timeSlots.map((time) => (
<tr key={time.date.ts}>
<td key={`right_${time.date.ts}`}>
{time.formatted}
</td>
{weekDays.map((day) => {
const slotValue = calculateSlotDate(day.date, time.date)
return (
<td
key={slotValue.toMillis()}
id={slotValue.toMillis()}
onClick={handleEntryCreation}
>
{events[slotValue.toMillis()] ?
<Box /> :
null
}
</td>
)
})}
<td key={`left_${time.date.ts}`}>{time.formatted}</td>
</tr>
))}
</tbody>
</table >
</div>
)
}
export default Calendar
.calendar {
td {
&:hover {
background-color: yellow;
}
width: 100%;
height: 50px;
display: flex;
justify-content: center;
padding: 0.25rem;
border-left: 0;
border-bottom: 0;
// user-select: none;
}
tr {
display: flex;
justify-content: center;
// height: 50px;
// align-items: center;
}
th {
text-align: center !important;
align-items: center;
justify-content: center;
border: 0 !important;
width: 100%;
user-select: none;
}
table {
// table-layout: fixed;
}
&-title {
text-align: center;
text-transform: capitalize;
}
&-today {
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
background-color: blue;
border-radius: 100%;
height: 40px;
width: 40px;
}
&-notToday {
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
height: 40px;
width: 40px;
}
}
.calendarbox {
&-container {
max-width: 100%;
display: flex;
margin: 0;
// position: relative;
z-index: 60;
}
// position: absolute;
width: 100px;
overflow: hidden;
height: 10px;
flex-grow: 1;
background-color: blue;
resize: vertical !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>