Skip to content

Commit fa9e132

Browse files
committed
feat: display the date of the next subs quota refresh
1 parent 065642d commit fa9e132

File tree

10 files changed

+70
-4
lines changed

10 files changed

+70
-4
lines changed

app/src/api/addition.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ type SubscriptionResponse = {
2020
usage: Record<string, number>;
2121
level: number;
2222
expired_at?: string;
23+
refresh?: number;
24+
refresh_at?: string;
2325
};
2426

2527
type BuySubscriptionResponse = {

app/src/resources/i18n/cn.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,8 @@
507507
"expired": "订阅剩余天数",
508508
"quota-manage": "订阅配额",
509509
"expired-days": "您的订阅将于 {{days}} 天后到期",
510+
"refresh-days": "您的配额将于 {{refresh_days}} 天后刷新",
511+
"get-refresh-days": "开始使用配额以获取刷新日期",
510512
"time": {
511513
"1": "1个月",
512514
"3": "3个月",

app/src/resources/i18n/en.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,9 @@
303303
"total-price": "Total Price",
304304
"upgrade-price-label": "Upgrading Cost",
305305
"upgrade-price-notice": "For information only",
306-
"upgrade-price-notice-tip": "The upgrade fee is for reference only, and the actual price is based on the exact calculation of the server."
306+
"upgrade-price-notice-tip": "The upgrade fee is for reference only, and the actual price is based on the exact calculation of the server.",
307+
"refresh-days": "Your quota will refresh in {{refresh_days}} days",
308+
"get-refresh-days": "Get started with quotas to get refresh dates"
307309
},
308310
"cancel": "Cancel",
309311
"confirm": "Confirm",

app/src/resources/i18n/ja.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,9 @@
303303
"total-price": "合計価格",
304304
"upgrade-price-label": "アップグレード料金",
305305
"upgrade-price-notice": "参考用",
306-
"upgrade-price-notice-tip": "アップグレード料金は参考用であり、実際の価格はサーバーの正確な計算に基づいています。"
306+
"upgrade-price-notice-tip": "アップグレード料金は参考用であり、実際の価格はサーバーの正確な計算に基づいています。",
307+
"refresh-days": "クォータは{{refresh_days}}日後に更新されます",
308+
"get-refresh-days": "クォータを使用して日付を更新する"
307309
},
308310
"cancel": "キャンセル",
309311
"confirm": "確認",

app/src/resources/i18n/ru.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,9 @@
303303
"total-price": "Общая цена",
304304
"upgrade-price-label": "Плата за повышение класса обслуживания",
305305
"upgrade-price-notice": "Только для информации",
306-
"upgrade-price-notice-tip": "Плата за обновление указана только для справки, а фактическая цена основана на точном расчете сервера."
306+
"upgrade-price-notice-tip": "Плата за обновление указана только для справки, а фактическая цена основана на точном расчете сервера.",
307+
"refresh-days": "Квота обновится через {{refresh_days}} дн.",
308+
"get-refresh-days": "Начните с квот, чтобы получить даты обновления"
307309
},
308310
"cancel": "Отмена",
309311
"confirm": "Подтвердить",

app/src/resources/i18n/tw.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,9 @@
375375
"upgrade-price-notice": "僅供參考",
376376
"upgrade-price-notice-tip": "升級費用僅供參考,實際價格以伺服器精準計算為準",
377377
"quota-manage": "訂閱配額",
378-
"expired-days": "您的訂閱將於 {{days}} 天後到期"
378+
"expired-days": "您的訂閱將於 {{days}} 天後到期",
379+
"refresh-days": "您的配額將於{{refresh_days}} 天後刷新",
380+
"get-refresh-days": "開始使用配額以取得刷新日期"
379381
},
380382
"cancel": "取消",
381383
"confirm": "確認",

app/src/routes/Wallet.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
isSubscribedSelector,
3131
levelSelector,
3232
usageSelector,
33+
refreshSelector,
3334
} from "@/store/subscription.ts";
3435
import { subscriptionDataSelector } from "@/store/globals.ts";
3536
import { motion, AnimatePresence } from "framer-motion";
@@ -256,6 +257,7 @@ function WalletPlanBox() {
256257
const subscription = useSelector(isSubscribedSelector);
257258
const level = useSelector(levelSelector);
258259
const expired = useSelector(expiredSelector);
260+
const refresh = useSelector(refreshSelector);
259261
const usage = useSelector(usageSelector);
260262
const [isYearly, setIsYearly] = useState(true);
261263
const subscriptionData = useSelector(subscriptionDataSelector);
@@ -379,6 +381,11 @@ function WalletPlanBox() {
379381
<p className="text-xs text-secondary">
380382
{t("sub.expired-days", { days: expired })}
381383
</p>
384+
<p className="text-xs text-secondary">
385+
{refresh > 0
386+
? t("sub.refresh-days", { refresh_days: refresh })
387+
: t("sub.get-refresh-days")}
388+
</p>
382389
</div>
383390
</AccordionTrigger>
384391
<AccordionContent className="p-0 h-fit">

app/src/store/subscription.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export const subscriptionSlice = createSlice({
99
enterprise: false,
1010
expired: 0,
1111
expired_at: "",
12+
refresh: 0,
13+
refresh_at: "",
1214
usage: {},
1315
},
1416
reducers: {},
@@ -25,6 +27,8 @@ export const subscriptionSlice = createSlice({
2527
state.enterprise = action.payload.enterprise || false;
2628
state.level = action.payload.level;
2729
state.expired_at = action.payload.expired_at || "";
30+
state.refresh = action.payload.refresh || 0;
31+
state.refresh_at = action.payload.refresh_at || "";
2832
});
2933
},
3034
});
@@ -38,6 +42,10 @@ export const expiredSelector = (state: any): number =>
3842
state.subscription.expired;
3943
export const expiredAtSelector = (state: any): string =>
4044
state.subscription.expired_at;
45+
export const refreshSelector = (state: any): number =>
46+
state.subscription.refresh;
47+
export const refreshAtSelector = (state: any): string =>
48+
state.subscription.refresh_at;
4149
export const usageSelector = (state: any): any => state.subscription.usage;
4250

4351
export const refreshSubscription = createAsyncThunk(

auth/controller.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,9 @@ func SubscriptionAPI(c *gin.Context) {
386386
"is_subscribed": false,
387387
"enterprise": false,
388388
"expired": 0,
389+
"expired_at": "1970-01-01 00:00:00",
390+
"refresh": 0,
391+
"refresh_at": "1970-01-01 00:00:00",
389392
"usage": channel.UsageMap{},
390393
})
391394
}
@@ -396,6 +399,9 @@ func SubscriptionAPI(c *gin.Context) {
396399
"is_subscribed": user.IsSubscribe(db),
397400
"enterprise": user.IsEnterprise(db),
398401
"expired": user.GetSubscriptionExpiredDay(db),
402+
"expired_at": user.GetSubscriptionExpiredAt(db).Format("2006-01-02 15:04:05"),
403+
"refresh": user.GetSubscriptionRefreshDay(db, cache),
404+
"refresh_at": user.GetSubscriptionRefreshAt(db, cache).Format("2006-01-02 15:04:05"),
399405
"usage": user.GetSubscriptionUsage(db, cache),
400406
})
401407
}

auth/usage.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,43 @@ package auth
33
import (
44
"chat/channel"
55
"database/sql"
6+
"math"
7+
"time"
8+
69
"github.com/go-redis/redis/v8"
710
)
811

912
func (u *User) GetSubscriptionUsage(db *sql.DB, cache *redis.Client) channel.UsageMap {
1013
plan := u.GetPlan(db)
1114
return plan.GetUsage(u, db, cache)
1215
}
16+
17+
func (u *User) GetSubscriptionRefreshAt(db *sql.DB, cache *redis.Client) time.Time {
18+
if disableSubscription() || !u.IsSubscribe(db) {
19+
return time.Unix(0, 0)
20+
}
21+
22+
plan := u.GetPlan(db)
23+
if len(plan.Items) == 0 {
24+
return time.Unix(0, 0)
25+
}
26+
27+
var next time.Time
28+
for i, item := range plan.Items {
29+
_, offset := channel.GetSubscriptionUsage(cache, u, item.Id)
30+
n := offset.AddDate(0, 1, 0)
31+
if i == 0 || n.Before(next) {
32+
next = n
33+
}
34+
}
35+
return next
36+
}
37+
38+
func (u *User) GetSubscriptionRefreshDay(db *sql.DB, cache *redis.Client) int {
39+
at := u.GetSubscriptionRefreshAt(db, cache)
40+
if at.Unix() <= 0 {
41+
return 0
42+
}
43+
diff := time.Until(at)
44+
return int(math.Round(diff.Hours() / 24))
45+
}

0 commit comments

Comments
 (0)