【问题标题】:What is the best way to find available hours from working hours从工作时间中找到可用时间的最佳方法是什么
【发布时间】:2020-10-13 18:08:12
【问题描述】:

我正在尝试为约会应用程序开发我的新项目。

我试图让用户为其业务选择开始时间和结束时间,然后让他的客户安排约会。

例如:

{
  openHour: '08:00',
  closeHour: '18:00',
  someServiceDuration: 900000 // 15 minutes in ms
}

我想向用户显示所有工作时间,但只有繁忙时间会被禁用。 例如:

<select name="available-hours">
  {workingHoursFromDB.map(({hour, isAvailable}) => {
     <option 
       value={hour} 
       disabled={isAvailable}>
       {hour}
     </option>
   })}
</select>

所以,假设工作时间在 08:00 到 18:00 之间,服务时间是 15 分钟,

如果有人在 08:10 到 08:25 之间安排约会,

将在选择元素中禁用的选项将是: 08:25、08:30、08:35 等等……

营业时间:08:00、08:05将停用,因为服务时间为 15 分钟,没有足够的时间进行新的预约。

我正在使用 React 和 MongoDB。 请告诉我完成此操作的最简单方法。 谢谢!

【问题讨论】:

    标签: javascript arrays reactjs mongodb mongoose


    【解决方案1】:

    我会避免根据预定日期计算可用时间段。

    您的选项列表很容易超过几百个元素。

    想象一下8:00, 8:01, 8:02, ..., 17:45

    在momentjs库的帮助下,它可以通过以下方式实现。

    const { useState, useEffect } = React;
    
    const duration = 15;
    const format = "YYYY-MM-DDTHH:mm";
    
    const getRange = (timePart) => {
       const [hour, minute] = timePart.split(':').map(pr => Number(pr));
      const from = moment().startOf('day').set({
        hour,
        minute
      });
      const to = from.clone().add(duration, 'minutes');
      
      return [from.format(format), to.format(format)];
    }
    
    const getWorkingHours = (() => {
      const today = moment().startOf('day');
        
      const from = today.set({hour: 8})
      const to = today.clone().set({hour: 18})
        
      const result = [from.format(format), to.format(format)];
      
      return () => result
    })()
    
    const getMockReservedDate = () => {
      const today = moment().startOf('day');
      
      const from = today.set({hour: 8, minute: 10});
      const to = today.clone().add(duration, 'minutes');
    
      const result = [from.format(format), to.format(format)];
      
      return result;
    }
    
    const App = () => {
      const [reserved, setReserved] = useState([
        getMockReservedDate()
      ]);
      const [value, setValue] = useState('');
      const [hasError, setError] = useState('');
      const [disabled, setDisabled] = useState(false);
      
      
      useEffect(() => {
        moment();
        
      }, [])
      
      const isBetweenWorkingHours = ([from, to]) => {
        const [start, end] = getWorkingHours()
        
        const fromMomentObj = moment(from);
        const toMomentObj = moment(to);
     
        if((!fromMomentObj.isBetween(start, end) 
          && !fromMomentObj.isSame(start))
        ||
          (!toMomentObj.isBetween(start, end)
          && !toMomentObj.isSame(end))
        ) {
          return false;
        }
        
        return true;
      }
      
      const onChange = ({target: {value}}) => {
        setValue(value);
        const range = getRange(value);
        
        if(!isBetweenWorkingHours(range)) {
          setError('Outside working hours');
          setDisabled(true);
          return;
        }
        
        for(const [from, to] of reserved) {
          const fromMomentObj = moment(range[0]);
          const toMomentObj = moment(range[1]);
        
          if(fromMomentObj.isBetween(from, to) ||
            toMomentObj.isBetween(from, to) ||
            fromMomentObj.isSame(from) ||
            toMomentObj.isSame(to)
          ) {
            setError(`Dates overlap ${from} -> ${to}`);
            setDisabled(true);
            
            return;
          }
        }
        
        setError('');
        setDisabled(false);
      }
      
      const onClick = () => {
        const range = getRange(value);
        
        setReserved(reserved => [...reserved, range])
        setValue('');
      }
      
      return <div>
          <div>Reserved {JSON.stringify(reserved)}</div>
        <div>
          <input min="08:00" max="18:00" required type="time" value={value} onChange={onChange}/>
          <div className={`message ${hasError ? 'error': ''}`}>{hasError}</div>
          <button disabled={disabled} onClick={onClick}>Submit</button>
        </div>
      </div>
    }
    
    ReactDOM.render(
        <App />,
        document.getElementById('root')
      );
    .message {
      display: none;
    }
    
    .error {
      display: block;
      color: red;
    }
    <script src="https://unpkg.com/react/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
    <div id="root"></div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-02
      • 2011-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-25
      • 1970-01-01
      • 2017-05-07
      相关资源
      最近更新 更多