Skip to content

Commit

Permalink
feat: update subscription life cycle
Browse files Browse the repository at this point in the history
  • Loading branch information
zmh-program committed Jan 16, 2024
1 parent dc5c6ed commit f8af707
Show file tree
Hide file tree
Showing 16 changed files with 123 additions and 182 deletions.
9 changes: 0 additions & 9 deletions app/src/api/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Conversation } from "./conversation.ts";
import React from "react";

export type Message = {
role: string;
Expand Down Expand Up @@ -49,11 +48,3 @@ export type Plan = {
};

export type Plans = Plan[];

export type SubscriptionUsage = Record<
string,
{
icon: React.ReactElement;
name: string;
}
>;
12 changes: 11 additions & 1 deletion app/src/api/v1.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import axios from "axios";
import { Model } from "@/api/types.ts";
import { Model, Plan } from "@/api/types.ts";
import { ChargeProps } from "@/admin/charge.ts";

export async function getApiModels(): Promise<string[]> {
Expand All @@ -12,6 +12,16 @@ export async function getApiModels(): Promise<string[]> {
}
}

export async function getApiPlans(): Promise<Plan[]> {
try {
const res = await axios.get("/v1/plans");
return res.data as Plan[];
} catch (e) {
console.warn(e);
return [];
}
}

export async function getApiMarket(): Promise<Model[]> {
try {
const res = await axios.get("/v1/market");
Expand Down
17 changes: 14 additions & 3 deletions app/src/components/app/AppProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ import { ThemeProvider } from "@/components/ThemeProvider.tsx";
import DialogManager from "@/dialogs";
import Broadcast from "@/components/Broadcast.tsx";
import { useEffectAsync } from "@/utils/hook.ts";
import { allModels, supportModels } from "@/conf";
import { allModels, subscriptionData, supportModels } from "@/conf";
import { channelModels } from "@/admin/channel.ts";
import { getApiCharge, getApiMarket, getApiModels } from "@/api/v1.ts";
import {
getApiCharge,
getApiMarket,
getApiModels,
getApiPlans,
} from "@/api/v1.ts";
import { loadPreferenceModels } from "@/utils/storage.ts";
import { resetJsArray } from "@/utils/base.ts";
import { useDispatch } from "react-redux";
import { initChatModels } from "@/store/chat.ts";
import { Model } from "@/api/types.ts";
import { Model, Plan } from "@/api/types.ts";
import { ChargeProps, nonBilling } from "@/admin/charge.ts";

function AppProvider() {
Expand Down Expand Up @@ -40,6 +45,12 @@ function AppProvider() {
if (!allModels.includes(model)) allModels.push(model);
if (!channelModels.includes(model)) channelModels.push(model);
});

const plans = await getApiPlans();
resetJsArray(
subscriptionData,
plans.filter((plan: Plan) => plan.level !== 0),
);
}, [allModels]);

return (
Expand Down
11 changes: 7 additions & 4 deletions app/src/components/app/MenuBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { openDialog as openApiDialog } from "@/store/api.ts";
import router from "@/router.tsx";
import { useDeeptrain } from "@/conf/env.ts";
import React from "react";
import { subscriptionData } from "@/conf";

type MenuBarProps = {
children: React.ReactNode;
Expand Down Expand Up @@ -61,10 +62,12 @@ function MenuBar({ children, className }: MenuBarProps) {
</>
)}
</DropdownMenuItem>
<DropdownMenuItem onClick={() => dispatch(openSub())}>
<CalendarPlus className={`h-4 w-4 mr-1`} />
{t("sub.title")}
</DropdownMenuItem>
{subscriptionData.length > 0 && (
<DropdownMenuItem onClick={() => dispatch(openSub())}>
<CalendarPlus className={`h-4 w-4 mr-1`} />
{t("sub.title")}
</DropdownMenuItem>
)}
{useDeeptrain && (
<DropdownMenuItem onClick={() => dispatch(openPackageDialog())}>
<Boxes className={`h-4 w-4 mr-1`} />
Expand Down
4 changes: 2 additions & 2 deletions app/src/components/home/ModelFinder.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import SelectGroup, { SelectItemProps } from "@/components/SelectGroup.tsx";
import { supportModels } from "@/conf";
import { subscriptionData, supportModels } from "@/conf";
import {
openMarket,
selectModel,
Expand Down Expand Up @@ -84,7 +84,7 @@ function ModelFinder(props: ModelSelectorProps) {
value: t("market.model"),
},
];
}, [supportModels, level, student, sync]);
}, [supportModels, subscriptionData, level, student, sync]);

const current = useMemo((): SelectItemProps => {
const raw = models.find((item) => item.name === model);
Expand Down
4 changes: 2 additions & 2 deletions app/src/components/home/ModelMarket.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
X,
} from "lucide-react";
import React, { useMemo, useState } from "react";
import { supportModels } from "@/conf";
import { subscriptionData, supportModels } from "@/conf";
import { isUrl, splitList } from "@/utils/base.ts";
import { Model } from "@/api/types.ts";
import { useDispatch, useSelector } from "react-redux";
Expand Down Expand Up @@ -123,7 +123,7 @@ function ModelItem({

const pro = useMemo(() => {
return includingModelFromPlan(level, model.id);
}, [model, level, student]);
}, [subscriptionData, model, level, student]);

const avatar = useMemo(() => {
return isUrl(model.avatar) ? model.avatar : `/icons/${model.avatar}`;
Expand Down
99 changes: 2 additions & 97 deletions app/src/conf/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,110 +12,15 @@ import { setAxiosConfig } from "@/conf/api.ts";
export const version = "3.8.6"; // version of the current build
export const dev: boolean = getDev(); // is in development mode (for debugging, in localhost origin)
export const deploy: boolean = true; // is production environment (for api endpoint)
export const tokenField = getTokenField(deploy); // token field name for storing token

export let apiEndpoint: string = getRestApi(deploy); // api endpoint for rest api calls
export let websocketEndpoint: string = getWebsocketApi(deploy); // api endpoint for websocket calls
export const tokenField = getTokenField(deploy); // token field name for storing token

export let supportModels: Model[] = loadPreferenceModels(getOfflineModels()); // support models in model market of the current site
export let allModels: string[] = supportModels.map((model) => model.id); // all support model id list of the current site

const GPT4Array = [
"gpt-4",
"gpt-4-0314",
"gpt-4-0613",
"gpt-4-1106-preview",
"gpt-4-vision-preview",
"gpt-4-v",
"gpt-4-dalle",
"gpt-4-all",
];
const Claude100kArray = ["claude-1.3", "claude-2", "claude-2.1"];
const MidjourneyArray = ["midjourney-fast"];

export const subscriptionData: Plans = [
{
level: 1,
price: 42,
items: [
{
id: "gpt-4",
icon: "compass",
name: "GPT-4",
value: 150,
models: GPT4Array,
},
{
id: "midjourney",
icon: "image-plus",
name: "Midjourney",
value: 50,
models: MidjourneyArray,
},
{
id: "claude-100k",
icon: "book-text",
name: "Claude 100k",
value: 300,
models: Claude100kArray,
},
],
},
{
level: 2,
price: 76,
items: [
{
id: "gpt-4",
icon: "compass",
name: "GPT-4",
value: 300,
models: GPT4Array,
},
{
id: "midjourney",
icon: "image-plus",
name: "Midjourney",
value: 100,
models: MidjourneyArray,
},
{
id: "claude-100k",
icon: "book-text",
name: "Claude 100k",
value: 600,
models: Claude100kArray,
},
],
},
{
level: 3,
price: 148,
items: [
{
id: "gpt-4",
icon: "compass",
name: "GPT-4",
value: 600,
models: GPT4Array,
},
{
id: "midjourney",
icon: "image-plus",
name: "Midjourney",
value: 200,
models: MidjourneyArray,
},
{
id: "claude-100k",
icon: "book-text",
name: "Claude 100k",
value: 1200,
models: Claude100kArray,
},
],
},
];
export let subscriptionData: Plans = []; // subscription data of the current site

setAxiosConfig({
endpoint: apiEndpoint,
Expand Down
6 changes: 5 additions & 1 deletion app/src/conf/subscription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ export function SubscriptionIcon({ type, className }: SubscriptionIconProps) {

export function getPlan(level: number): Plan {
const raw = subscriptionData.filter((item) => item.level === level);
return raw.length > 0 ? raw[0] : subscriptionData[0];
return raw.length > 0
? raw[0]
: subscriptionData.length
? subscriptionData[0]
: { level: 0, price: 0, items: [] };
}

export function getPlanModels(level: number): string[] {
Expand Down
19 changes: 11 additions & 8 deletions app/src/dialogs/QuotaDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { ToastAction } from "@/components/ui/toast.tsx";
import { deeptrainEndpoint, docsEndpoint, useDeeptrain } from "@/conf/env.ts";
import { useRedeem } from "@/api/redeem.ts";
import { cn } from "@/components/ui/lib/utils.ts";
import { subscriptionData } from "@/conf";

type AmountComponentProps = {
amount: number;
Expand Down Expand Up @@ -105,14 +106,16 @@ function QuotaDialog() {
<DialogTitle>{t("buy.choose")}</DialogTitle>
<DialogDescription asChild>
<div className={`dialog-wrapper`}>
<p
className={`link translate-y-2 text-center`}
onClick={() =>
sub ? dispatch(closeDialog()) : dispatch(openSubDialog())
}
>
{t("sub.subscription-link")}
</p>
{subscriptionData.length > 0 && (
<p
className={`link translate-y-2 text-center`}
onClick={() =>
sub ? dispatch(closeDialog()) : dispatch(openSubDialog())
}
>
{t("sub.subscription-link")}
</p>
)}
<div className={`buy-interface`}>
<div className={`interface-item`}>
<div className={`amount-container`}>
Expand Down
4 changes: 2 additions & 2 deletions app/src/dialogs/SubscriptionDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ type PlanItemProps = {
function PlanItem({ level }: PlanItemProps) {
const { t } = useTranslation();
const current = useSelector(levelSelector);
const plan = useMemo(() => getPlan(level), [level]);
const name = useMemo(() => getPlanName(level), [level]);
const plan = useMemo(() => getPlan(level), [subscriptionData, level]);
const name = useMemo(() => getPlanName(level), [subscriptionData, level]);

return (
<div className={cn("plan", name)}>
Expand Down
3 changes: 3 additions & 0 deletions app/src/store/subscription.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createSlice } from "@reduxjs/toolkit";
import { getSubscription } from "@/api/addition.ts";
import { AppDispatch } from "./index.ts";
import { subscriptionData } from "@/conf";

export const subscriptionSlice = createSlice({
name: "subscription",
Expand All @@ -16,12 +17,14 @@ export const subscriptionSlice = createSlice({
},
reducers: {
toggleDialog: (state) => {
if (!state.dialog && !subscriptionData.length) return;
state.dialog = !state.dialog;
},
setDialog: (state, action) => {
state.dialog = action.payload as boolean;
},
openDialog: (state) => {
if (!subscriptionData.length) return;
state.dialog = true;
},
closeDialog: (state) => {
Expand Down
Loading

0 comments on commit f8af707

Please sign in to comment.