File size: 6,060 Bytes
f0743f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import React from 'react';
import { Label, InfoHoverCard, ESide } from '@librechat/client';
import { TranslationKeys, useLocalize } from '~/hooks';

interface AutoRefillSettingsProps {
  lastRefill: Date;
  refillAmount: number;
  refillIntervalUnit: 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months';
  refillIntervalValue: number;
}

/**
 * Adds a time interval to a given date.
 * @param {Date} date - The starting date.
 * @param {number} value - The numeric value of the interval.
 * @param {'seconds'|'minutes'|'hours'|'days'|'weeks'|'months'} unit - The unit of time.
 * @returns {Date} A new Date representing the starting date plus the interval.
 */
const addIntervalToDate = (
  date: Date,
  value: number,
  unit: 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months',
): Date => {
  const result = new Date(date);
  switch (unit) {
    case 'seconds':
      result.setSeconds(result.getSeconds() + value);
      break;
    case 'minutes':
      result.setMinutes(result.getMinutes() + value);
      break;
    case 'hours':
      result.setHours(result.getHours() + value);
      break;
    case 'days':
      result.setDate(result.getDate() + value);
      break;
    case 'weeks':
      result.setDate(result.getDate() + value * 7);
      break;
    case 'months':
      result.setMonth(result.getMonth() + value);
      break;
    default:
      break;
  }
  return result;
};

/**
 * Calculates the next future refill date.
 * This function determines how many intervals have passed since the base date
 * and advances to the next eligible date. It correctly handles both fixed-duration
 * intervals (e.g., days, weeks) and variable-duration intervals (e.g., months).
 *
 * @param {Date} baseDate - The starting date for the calculation (e.g., the last refill date).
 * @param {number} value - The numeric value of the interval (e.g., 7 for 7 days).
 * @param {'seconds'|'minutes'|'hours'|'days'|'weeks'|'months'} unit - The unit of time for the interval.
 * @returns {Date} The next calculated future refill date.
 */
function getNextFutureInterval(
  baseDate: Date,
  value: number,
  unit: 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months',
): Date {
  const now = new Date();

  if (baseDate > now) {
    return addIntervalToDate(baseDate, value, unit);
  }

  if (unit === 'months') {
    let nextRefillDate = new Date(baseDate);
    while (nextRefillDate <= now) {
      nextRefillDate = addIntervalToDate(nextRefillDate, value, unit);
    }
    return nextRefillDate;
  }

  const intervalInMs = {
    seconds: value * 1000,
    minutes: value * 1000 * 60,
    hours: value * 1000 * 60 * 60,
    days: value * 1000 * 60 * 60 * 24,
    weeks: value * 1000 * 60 * 60 * 24 * 7,
  }[unit];

  if (intervalInMs <= 0) {
    return addIntervalToDate(baseDate, value, unit);
  }

  const timeSinceBase = now.getTime() - baseDate.getTime();
  const intervalsPassed = Math.floor(timeSinceBase / intervalInMs);
  const intervalsToNext = intervalsPassed + 1;
  const nextRefillTime = baseDate.getTime() + intervalsToNext * intervalInMs;

  return new Date(nextRefillTime);
}

const AutoRefillSettings: React.FC<AutoRefillSettingsProps> = ({
  lastRefill,
  refillAmount,
  refillIntervalUnit,
  refillIntervalValue,
}) => {
  const localize = useLocalize();

  const lastRefillDate = lastRefill ? new Date(lastRefill) : null;
  const nextRefill = lastRefillDate
    ? getNextFutureInterval(lastRefillDate, refillIntervalValue, refillIntervalUnit)
    : null;

  // Return the localized unit based on singular/plural values
  const getLocalizedIntervalUnit = (
    value: number,
    unit: 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months',
  ): string => {
    let key: TranslationKeys;
    switch (unit) {
      case 'seconds':
        key = value === 1 ? 'com_nav_balance_second' : 'com_nav_balance_seconds';
        break;
      case 'minutes':
        key = value === 1 ? 'com_nav_balance_minute' : 'com_nav_balance_minutes';
        break;
      case 'hours':
        key = value === 1 ? 'com_nav_balance_hour' : 'com_nav_balance_hours';
        break;
      case 'days':
        key = value === 1 ? 'com_nav_balance_day' : 'com_nav_balance_days';
        break;
      case 'weeks':
        key = value === 1 ? 'com_nav_balance_week' : 'com_nav_balance_weeks';
        break;
      case 'months':
        key = value === 1 ? 'com_nav_balance_month' : 'com_nav_balance_months';
        break;
      default:
        key = 'com_nav_balance_seconds';
    }
    return localize(key);
  };

  return (
    <div className="space-y-4">
      <h3 className="text-lg font-medium">{localize('com_nav_balance_auto_refill_settings')}</h3>
      <div className="mb-1 flex justify-between text-sm">
        <span>{localize('com_nav_balance_last_refill')}</span>
        <span>{lastRefillDate ? lastRefillDate.toLocaleString() : '-'}</span>
      </div>
      <div className="mb-1 flex justify-between text-sm">
        <span>{localize('com_nav_balance_refill_amount')}</span>
        <span>{refillAmount !== undefined ? refillAmount : '-'}</span>
      </div>
      <div className="mb-1 flex justify-between text-sm">
        <span>{localize('com_nav_balance_interval')}</span>
        <span>
          {localize('com_nav_balance_every')} {refillIntervalValue}{' '}
          {getLocalizedIntervalUnit(refillIntervalValue, refillIntervalUnit)}
        </span>
      </div>
      <div className="flex items-center justify-between">
        {/* Left Section: Label */}
        <div className="flex items-center space-x-2">
          <Label className="font-light">{localize('com_nav_balance_next_refill')}</Label>
          <InfoHoverCard side={ESide.Bottom} text={localize('com_nav_balance_next_refill_info')} />
        </div>

        {/* Right Section: tokenCredits Value */}
        <span className="text-sm font-medium text-gray-800 dark:text-gray-200" role="note">
          {nextRefill ? nextRefill.toLocaleString() : '-'}
        </span>
      </div>
    </div>
  );
};

export default AutoRefillSettings;