You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mantine Calendar自定义故障:无法标记房间占用日期

Mantine Calendar组件自定义:标记已占用日期为红色

我是Mantine库的新手,希望自定义其Calendar组件,使有房间被占用的日期显示为红色。数据库及后台逻辑均正常运行,此前在react-calendar上已实现该功能,但想要开箱即用的现代外观样式。我找不到相关教程来排查问题或实现需求。

我尝试的代码

第一次尝试:通过styles属性自定义

"use client";

import React, { useState } from "react";
import { Calendar, CalendarStylesNames } from "@mantine/dates";
import { Booking } from "../types";
import "@mantine/dates/styles.css";

interface CalendarProps {
  bookings: Booking[];
}

const MyCalendar: React.FC<CalendarProps> = ({ bookings }) => {
  const [value, setValue] = useState<Date | null>(new Date());

  const isDateOccupied = (date: Date) => {
    return (
      Array.isArray(bookings) &&
      bookings.some(
        (booking) =>
          new Date(booking.check_in_date) <= date &&
          new Date(booking.check_out_date) >= date
      )
    );
  };

  const getOccupiedRoomsForDate = (date: Date) => {
    return bookings
      .filter(
        (booking) =>
          new Date(booking.check_in_date) <= date &&
          new Date(booking.check_out_date) >= date
      )
      .map((booking) => booking.room_number);
  };

  return (
    <div>
      <Calendar
        value={value}
        onChange={setValue}
        styles={{
          day: (occupied: any) => ({
            backgroundColor: occupied ? "#ff6b6b" : "#ffffff",
            color: occupied ? "#ffffff" : "#000000",
          }),
        }}
        size="md"
      />
    </div>
  );
};

export default MyCalendar;

第二次尝试:使用dayStyle函数

const getDayStyle = (date: Date, params: CalendarStylesParams) => {
  const isOccupied = isDateOccupied(date);

  return {
    backgroundColor: isOccupied
      ? "#ff6b6b"
      : params.day.weekend
      ? "#f0f0f0"
      : "#ffffff",
    color: isOccupied ? "#ffffff" : "#000000",
    cursor: "pointer",
  };
};

return (
  <Calendar
    value={value}
    onChange={setValue}
    dayStyle={getDayStyle}
  />
);

解决方案

你的问题主要出在样式函数的参数使用错误以及日期比较的精度问题,以下是修正后的实现:

1. 修复日期比较逻辑

日期比较时需要统一时间部分(将时分秒设为0),避免具体时间干扰判断:

const normalizeDate = (date: Date) => {
  const normalized = new Date(date);
  normalized.setHours(0, 0, 0, 0);
  return normalized;
};

const isDateOccupied = (date: Date) => {
  const targetDate = normalizeDate(date);
  return Array.isArray(bookings) && bookings.some((booking) => {
    const checkIn = normalizeDate(new Date(booking.check_in_date));
    const checkOut = normalizeDate(new Date(booking.check_out_date));
    // 可根据业务逻辑调整:如果退房当天允许入住,这里用checkOut > targetDate
    return checkIn <= targetDate && checkOut > targetDate;
  });
};

2. 使用正确的dayStyle属性(Mantine v7)

Mantine的Calendar组件中,dayStyle函数的参数是包含date、weekend、selected等字段的对象,修正后的完整代码:

"use client";

import React, { useState } from "react";
import { Calendar } from "@mantine/dates";
import { Booking } from "../types";
import "@mantine/dates/styles.css";

interface CalendarProps {
  bookings: Booking[];
}

const MyCalendar: React.FC<CalendarProps> = ({ bookings }) => {
  const [value, setValue] = useState<Date | null>(new Date());

  const normalizeDate = (date: Date) => {
    const normalized = new Date(date);
    normalized.setHours(0, 0, 0, 0);
    return normalized;
  };

  const isDateOccupied = (date: Date) => {
    const targetDate = normalizeDate(date);
    return Array.isArray(bookings) && bookings.some((booking) => {
      const checkIn = normalizeDate(new Date(booking.check_in_date));
      const checkOut = normalizeDate(new Date(booking.check_out_date));
      return checkIn <= targetDate && checkOut > targetDate;
    });
  };

  return (
    <div>
      <Calendar
        value={value}
        onChange={setValue}
        size="md"
        dayStyle={({ date, weekend }) => {
          const occupied = isDateOccupied(date);
          return {
            backgroundColor: occupied 
              ? "#ff6b6b" 
              : weekend 
                ? "#f8fafc" 
                : "transparent",
            color: occupied ? "#ffffff" : "#1e293b",
            borderRadius: "4px",
            "&:hover": {
              backgroundColor: occupied ? "#e55555" : "#f1f5f9",
            },
          };
        }}
      />
    </div>
  );
};

export default MyCalendar;

3. 结合Tailwind的写法(可选)

如果你习惯用Tailwind,可通过dayStyle返回className实现:

dayStyle={({ date, weekend }) => {
  const occupied = isDateOccupied(date);
  return {
    className: `rounded-md ${
      occupied 
        ? "bg-red-500 text-white hover:bg-red-600" 
        : weekend 
          ? "bg-gray-100 hover:bg-gray-200" 
          : "hover:bg-gray-100"
    }`,
  };
}}

关键说明

  • Mantine样式函数的参数需匹配组件定义的类型,可通过编辑器类型提示确认参数结构。
  • 日期归一化是避免时间干扰判断的核心步骤,必须处理时分秒。
  • 若使用Mantine v6,API逻辑一致,但样式优先级需注意组件默认样式的覆盖。

内容的提问来源于stack exchange,提问作者1r2t3z

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:47:11