feat: vip按钮
This commit is contained in:
parent
9cb214d67f
commit
aeff96032e
16
components/BuyVipButton.tsx
Normal file
16
components/BuyVipButton.tsx
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
// BuyVipButton 组件
|
||||||
|
function BuyVipButton() {
|
||||||
|
// 这是购买VIP的目标URL
|
||||||
|
const targetUrl = "https://store.paperai.life";
|
||||||
|
return (
|
||||||
|
<a href={targetUrl} target="_blank" className="no-underline">
|
||||||
|
<button className="bg-gold text-white font-semibold text-lg py-2 px-4 rounded cursor-pointer border-none shadow-md transition duration-300 ease-in-out transform hover:scale-110 ">
|
||||||
|
Buy VIP TO UNLOCK Cloud Sync and Edit Mutiple Papers Simultaneously
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BuyVipButton;
|
|
@ -1,7 +1,7 @@
|
||||||
"use client";
|
"use client";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useAppDispatch } from "@/app/store"; // 确保路径正确
|
import { useAppDispatch } from "@/app/store";
|
||||||
import { setShowPaperManagement } from "@/app/store/slices/stateSlice"; // 确保路径正确
|
import { setShowPaperManagement } from "@/app/store/slices/stateSlice";
|
||||||
|
|
||||||
export default function PaperListButton() {
|
export default function PaperListButton() {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
|
@ -19,11 +19,14 @@ import {
|
||||||
getUserPaper,
|
getUserPaper,
|
||||||
submitPaper,
|
submitPaper,
|
||||||
deletePaper,
|
deletePaper,
|
||||||
|
fetchUserVipStatus,
|
||||||
} from "@/utils/supabase/supabaseutils";
|
} from "@/utils/supabase/supabaseutils";
|
||||||
//动画
|
//动画
|
||||||
import { CSSTransition } from "react-transition-group";
|
import { CSSTransition } from "react-transition-group";
|
||||||
//删除远程论文按钮
|
//删除远程论文按钮
|
||||||
import ParagraphDeleteButton from "@/components/ParagraphDeleteInterface";
|
import ParagraphDeleteButton from "@/components/ParagraphDeleteInterface";
|
||||||
|
//vip充值按钮
|
||||||
|
import BuyVipButton from "@/components/BuyVipButton"; // 假设这是购买VIP的按钮组件
|
||||||
|
|
||||||
const PaperManagement = () => {
|
const PaperManagement = () => {
|
||||||
//supabase
|
//supabase
|
||||||
|
@ -36,29 +39,43 @@ const PaperManagement = () => {
|
||||||
const showPaperManagement = useAppSelector(
|
const showPaperManagement = useAppSelector(
|
||||||
(state) => state.state.showPaperManagement
|
(state) => state.state.showPaperManagement
|
||||||
);
|
);
|
||||||
//状态
|
//获取的论文数量列表状态
|
||||||
const [paperNumbers, setPaperNumbers] = useState<string[]>([]);
|
const [paperNumbers, setPaperNumbers] = useState<string[]>([]);
|
||||||
//user id的状态设置
|
//user id的状态设置
|
||||||
const [userId, setUserId] = useState<string>("");
|
const [userId, setUserId] = useState<string>("");
|
||||||
|
//vip状态
|
||||||
|
const [isVip, setIsVip] = useState(false);
|
||||||
|
|
||||||
//获取用户存储在云端的论文
|
//获取用户存储在云端的论文,使用useCallback定义一个记忆化的函数来获取用户论文
|
||||||
// 使用useCallback定义一个记忆化的函数来获取用户论文
|
|
||||||
const fetchPapers = useCallback(async () => {
|
const fetchPapers = useCallback(async () => {
|
||||||
const user = await getUser(supabase);
|
const user = await getUser(supabase);
|
||||||
if (user && user.id) {
|
if (user && user.id) {
|
||||||
const numbers = await getUserPaperNumbers(user.id);
|
const numbers = await getUserPaperNumbers(user.id, supabase);
|
||||||
setPaperNumbers(numbers || []); // 直接在这里更新状态
|
setPaperNumbers(numbers || []); // 直接在这里更新状态
|
||||||
setUserId(user.id);
|
setUserId(user.id);
|
||||||
}
|
}
|
||||||
}, [supabase]); // 依赖项数组中包含supabase,因为它可能会影响到fetchPapers函数的结果
|
}, [supabase]); // 依赖项数组中包含supabase,因为它可能会影响到fetchPapers函数的结果
|
||||||
|
|
||||||
|
//获取用户VIP状态
|
||||||
|
const initFetch = async () => {
|
||||||
|
const user = await getUser();
|
||||||
|
if (user && user.id) {
|
||||||
|
const isVip = await fetchUserVipStatus(user.id);
|
||||||
|
console.log("isVip", isVip);
|
||||||
|
setIsVip(isVip);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
initFetch();
|
||||||
|
}, []);
|
||||||
|
|
||||||
// 使用useEffect在组件挂载后立即获取数据
|
// 使用useEffect在组件挂载后立即获取数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchPapers();
|
fetchPapers();
|
||||||
}, [fetchPapers]);
|
}, [fetchPapers]);
|
||||||
|
|
||||||
const handlePaperClick = async (paperNumber: string) => {
|
const handlePaperClick = async (paperNumber: string) => {
|
||||||
const data = await getUserPaper(userId, paperNumber); // 假设这个函数异步获取论文内容
|
const data = await getUserPaper(userId, paperNumber, supabase); // 假设这个函数异步获取论文内容
|
||||||
if (!data) {
|
if (!data) {
|
||||||
throw new Error("查询出错");
|
throw new Error("查询出错");
|
||||||
}
|
}
|
||||||
|
@ -71,20 +88,26 @@ const PaperManagement = () => {
|
||||||
dispatch(setContentUpdatedFromNetwork(true)); // 更新 Redux store
|
dispatch(setContentUpdatedFromNetwork(true)); // 更新 Redux store
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getNextPaperNumber(paperNumbers: string[]) {
|
||||||
|
if (paperNumbers.length === 0) {
|
||||||
|
return "1";
|
||||||
|
} else {
|
||||||
|
return String(Math.max(...paperNumbers.map(Number)) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleAddPaperClick = async () => {
|
const handleAddPaperClick = async () => {
|
||||||
// 添加一个新的空白论文
|
// 添加一个新的空白论文
|
||||||
await submitPaper(
|
await submitPaper(
|
||||||
supabase,
|
supabase,
|
||||||
"This is a blank page",
|
"This is a blank page",
|
||||||
[],
|
[],
|
||||||
String(Math.max(...paperNumbers.map(Number)) + 1)
|
getNextPaperNumber(paperNumbers)
|
||||||
);
|
);
|
||||||
// 重新获取论文列表
|
// 重新获取论文列表
|
||||||
await fetchPapers();
|
await fetchPapers();
|
||||||
};
|
};
|
||||||
|
|
||||||
const noop = (...args: any) => {};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CSSTransition
|
<CSSTransition
|
||||||
in={showPaperManagement}
|
in={showPaperManagement}
|
||||||
|
@ -97,55 +120,61 @@ const PaperManagement = () => {
|
||||||
<div className="max-w-md w-full bg-blue-gray-100 rounded overflow-hidden shadow-lg mx-auto p-5">
|
<div className="max-w-md w-full bg-blue-gray-100 rounded overflow-hidden shadow-lg mx-auto p-5">
|
||||||
<h1 className="font-bold text-3xl text-center">Paper Management</h1>
|
<h1 className="font-bold text-3xl text-center">Paper Management</h1>
|
||||||
</div>
|
</div>
|
||||||
<button
|
{isVip ? (
|
||||||
onClick={handleAddPaperClick}
|
<div>
|
||||||
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
|
<button
|
||||||
>
|
onClick={handleAddPaperClick}
|
||||||
+ Add Paper
|
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
|
||||||
</button>
|
>
|
||||||
<div className="flex flex-col items-center space-y-2">
|
+ Add Paper
|
||||||
<h2 className="text-xl font-semibold">Your Papers</h2>
|
</button>
|
||||||
{paperNumbers.length > 0 ? (
|
<div className="flex flex-col items-center space-y-2">
|
||||||
<ul className="list-disc">
|
<h2 className="text-xl font-semibold">Your Papers</h2>
|
||||||
{[...paperNumbers]
|
{paperNumbers.length > 0 ? (
|
||||||
.sort((a, b) => parseInt(a, 10) - parseInt(b, 10))
|
<ul className="list-disc">
|
||||||
.map((number, index) => (
|
{[...paperNumbers]
|
||||||
<li
|
.sort((a, b) => parseInt(a, 10) - parseInt(b, 10))
|
||||||
key={index}
|
.map((number, index) => (
|
||||||
className={`bg-white w-full max-w-md mx-auto rounded shadow p-4 cursor-pointer ${
|
<li
|
||||||
number === paperNumberRedux ? "bg-yellow-200" : ""
|
key={index}
|
||||||
}`}
|
className={`bg-white w-full max-w-md mx-auto rounded shadow p-4 cursor-pointer ${
|
||||||
onClick={() => handlePaperClick(number)}
|
number === paperNumberRedux ? "bg-yellow-200" : ""
|
||||||
>
|
}`}
|
||||||
<span>Paper {number}</span>
|
onClick={() => handlePaperClick(number)}
|
||||||
<ParagraphDeleteButton
|
>
|
||||||
index={index}
|
<span>Paper {number}</span>
|
||||||
removeReferenceUpdateIndex={async () => {
|
<ParagraphDeleteButton
|
||||||
await deletePaper(supabase, userId, number);
|
index={index}
|
||||||
const numbers = await getUserPaperNumbers(
|
removeReferenceUpdateIndex={async () => {
|
||||||
userId,
|
await deletePaper(supabase, userId, number);
|
||||||
supabase
|
const numbers = await getUserPaperNumbers(
|
||||||
);
|
userId,
|
||||||
setPaperNumbers(numbers || []); // 直接在这里更新状态
|
supabase
|
||||||
}}
|
);
|
||||||
isRemovePaper={true}
|
setPaperNumbers(numbers || []); // 直接在这里更新状态
|
||||||
title="Do you want to delete this paper?"
|
}}
|
||||||
text="This action cannot be undone"
|
isRemovePaper={true}
|
||||||
></ParagraphDeleteButton>
|
title="Do you want to delete this paper?"
|
||||||
{/* <input
|
text="This action cannot be undone"
|
||||||
|
></ParagraphDeleteButton>
|
||||||
|
{/* <input
|
||||||
type="text"
|
type="text"
|
||||||
value={paper.title}
|
value={paper.title}
|
||||||
onChange={(e) => handleTitleChange(index, e.target.value)}
|
onChange={(e) => handleTitleChange(index, e.target.value)}
|
||||||
placeholder="Enter paper title"
|
placeholder="Enter paper title"
|
||||||
className="mt-2 p-2 border rounded"
|
className="mt-2 p-2 border rounded"
|
||||||
/> */}
|
/> */}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
) : (
|
) : (
|
||||||
<p>No papers found.</p>
|
<p>No papers found.</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<BuyVipButton />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
|
|
|
@ -147,11 +147,14 @@ export async function fetchUserVipStatus(userId: string) {
|
||||||
.select("is_vip")
|
.select("is_vip")
|
||||||
.eq("user_id", userId)
|
.eq("user_id", userId)
|
||||||
.single();
|
.single();
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error("Error fetching VIP status:", error);
|
console.error("Error fetching VIP status:", error);
|
||||||
return null;
|
return false;
|
||||||
|
}
|
||||||
|
if ("is_vip" in data) {
|
||||||
|
console.log("VIP status:", data.is_vip);
|
||||||
|
return data.is_vip;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data?.is_vip;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user