简体   繁体   中英

ReactJS — How to create a flexible start date in a Calendar Component?

I am trying to create a single month Calendar Component where the starting date is flexible, therefore the first day of the month can start during any weekday (ie M, T, W). I manage to create the grid, but I am struggling to get start flexibility. Can anyone help me to figure it out?

Thank you in advance.

Logic - Image

Render result - Image

JavaScript

 $(function(){ var $container = $("#container"); var boxCount = 31, rowLength = 7, boxSize = 414 / 7; for(var i=0; i<boxCount; i++){ var $box = $("<div/>") .attr("class", "box") .css({ left: i%rowLength * boxSize + "px", top: Math.floor(i/rowLength) * boxSize }) .appendTo($container); } }); 
 #container{ position: relative; } .box{ position: absolute; width: 50px; height: 50px; background: #eee; border-radius: 1px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id="container"></div> 

ReactJS

import * as React from 'react'
import { PropertyControls, ControlType } from 'framer'

// Define type of property
interface Props {
    width: number
    height: number
    text: string
    number: number
}

export class Calendar extends React.Component<Props> {
    // Set default properties
    static defaultProps = {
        text: 'January',
        number: 31,
    }

    // Items shown in property panel
    static propertyControls: PropertyControls = {
        text: { type: ControlType.String, title: 'Month' },

        number: {
            type: ControlType.Number,
            title: 'Number',
            min: 0,
            max: 100,
            step: 1,
            displayStepper: true,
        },
    }

    render() {
        const createCalendar = (month, number, width, height) => {
            var rowLength = 7,
                boxWidth = width / rowLength,
                boxHeight = height / rowLength,
                times = 2

            // const leftPos = i => {
            //  console.log((i % rowLength) * boxWidth)
            //  var offset = boxWidth * times
            //  if (i < rowLength - times) {
            //      var offset = boxWidth * times
            //      return (i % rowLength) * boxWidth + offset
            //  } else if (i >= 5 && i <= 6) {
            //      return (i % (rowLength - times)) * boxWidth
            //  } else if (i >= rowLength) {
            //      return (i % rowLength) * boxWidth + offset
            //  }
            // }

            // LOGIC
            const leftPos = i => {
                console.log((i % rowLength) * boxWidth)
                var offset = boxWidth * times
                if (i < rowLength - times) {
                    var offset = boxWidth * times
                    return (i % 5) * boxWidth + offset
                } else {
                    return (i % 5) * boxWidth
                }
            }

            const topPos = i => {
                return Math.floor(i / (rowLength - times)) * boxHeight
            }

            const res = [ ...Array(number) ].map((_, i) => {
                return (
                    <div
                        style={{
                            position: 'absolute',
                            width: boxWidth,
                            height: boxHeight,
                            // left: (i % rowLength) * boxWidth + boxWidth * 2,
                            left: leftPos(i),
                            // top: Math.floor(i / rowLength) * boxHeight,
                            top: topPos(i),
                            display: 'flex',
                            alignItems: 'center',
                            justifyContent: 'center',
                            textAlign: 'center',
                            color: '#8855FF',
                            background: 'rgba(136, 85, 255, 0.1)',
                            overflow: 'hidden',
                        }}
                        key={i}
                    >
                        {i + 1}
                    </div>
                )
            })
            return (
                <div
                    style={{
                        display: 'flex',
                        flexDirection: 'column',
                    }}
                >
                    <div
                        style={{
                            display: 'flex',
                            alignItems: 'center',
                            justifyContent: `center`,
                            textAlign: 'center',
                            width: '100%',
                            height: boxHeight,
                            color: '#8855FF',
                            background: 'rgba(136, 85, 255, 0.1)',
                        }}
                    >
                        {month}
                    </div>
                    <div style={{ position: 'relative' }}>{res}</div>
                </div>
            )
        }
        return createCalendar(this.props.text, this.props.number, this.props.width, this.props.height)
    }
}

You can try a library like date-fns: https://date-fns.org/docs/Getting-Started

Start your month with dateFns.startOfWeek(dateFns.startOfMonth(new Date())) (or start of the week of the date you want) and hide the other days with css: https://codepen.io/pen/ZwrQZg

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM