完成热门管理
This commit is contained in:
parent
abfbfbb95e
commit
0aab21db19
|
@ -0,0 +1,5 @@
|
||||||
|
import { atom } from 'jotai';
|
||||||
|
|
||||||
|
// 定义一个简单的原子
|
||||||
|
export const linkTypeAtom = atom('');
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Link as _Link } from "../api/link/route";
|
||||||
import { LinkType } from "../api/linkType/route";
|
import { LinkType } from "../api/linkType/route";
|
||||||
|
|
||||||
export default function LinkListBox({ linkTypeList, linkList }: { linkTypeList: LinkType[]; linkList: _Link[] }) {
|
export default function LinkListBox({ linkTypeList, linkList }: { linkTypeList: LinkType[]; linkList: _Link[] }) {
|
||||||
return <div className="flex w-full flex-col gap-y-2">
|
return <div className="flex w-full flex-col gap-y-4">
|
||||||
{
|
{
|
||||||
linkTypeList.map(item => (
|
linkTypeList.map(item => (
|
||||||
<div className="flex flex-col gap-y-2" key={item._id}>
|
<div className="flex flex-col gap-y-2" key={item._id}>
|
||||||
|
@ -17,11 +17,11 @@ export default function LinkListBox({ linkTypeList, linkList }: { linkTypeList:
|
||||||
{
|
{
|
||||||
linkList.filter(val => val.type === item._id).map(val => (
|
linkList.filter(val => val.type === item._id).map(val => (
|
||||||
<Link key={val._id} className="flex gap-x-2 bg-white rounded-lg py-4 pl-2 cursor-pointer duration-150 hover:-translate-y-1 shadow-sm"
|
<Link key={val._id} className="flex gap-x-2 bg-white rounded-lg py-4 pl-2 cursor-pointer duration-150 hover:-translate-y-1 shadow-sm"
|
||||||
href={val.link || ''}>
|
href={val.link || ''} target="_blank">
|
||||||
<img src={val.logoLink} className="w-[40px] h-[40px]"></img>
|
<img src={val.logoLink} className="w-[40px] h-[40px]"></img>
|
||||||
<div className="flex-1 w-0 flex flex-col justify-between">
|
<div className="flex-1 w-0 flex flex-col justify-between">
|
||||||
<span className=" font-bold text-ellipsis overflow-hidden whitespace-nowrap">{val.name}</span>
|
<span className=" font-bold text-ellipsis overflow-hidden whitespace-nowrap">{val.name}</span>
|
||||||
<span className=" text-ellipsis overflow-hidden whitespace-nowrap text-[#666] text-xs">{val.description}</span>
|
<span className=" text-ellipsis overflow-hidden whitespace-nowrap text-[#666] text-xs" title={val.description}>{val.description}</span>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
))
|
))
|
||||||
|
|
|
@ -82,7 +82,7 @@ export default function Search() {
|
||||||
}
|
}
|
||||||
}, [activeSearchKey])
|
}, [activeSearchKey])
|
||||||
return (
|
return (
|
||||||
<div className="w-full flex justify-center flex-col items-center py-10">
|
<div className="w-full flex justify-center flex-col items-center py-10 ">
|
||||||
|
|
||||||
<div className="w-[200px]">
|
<div className="w-[200px]">
|
||||||
<Logo></Logo>
|
<Logo></Logo>
|
||||||
|
|
|
@ -5,17 +5,19 @@ import Logo from "./Logo";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import { LinkType } from "../api/linkType/route";
|
import { LinkType } from "../api/linkType/route";
|
||||||
|
import { useAtom } from "jotai";
|
||||||
|
import { linkTypeAtom } from "../_lib/atom";
|
||||||
|
|
||||||
export default function SiderNav({ linkList }: { linkList: LinkType[] }) {
|
export default function SiderNav({ linkList }: { linkList: LinkType[] }) {
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
console.log(pathname);
|
console.log(pathname);
|
||||||
|
const [selectType, setSelectType] = useAtom(linkTypeAtom)
|
||||||
return (
|
return (
|
||||||
<div className="w-[220px] flex flex-col gap-y-2 fixed left-0 top-0 h-[100vh] bg-[#F9F9F9]">
|
<div className="w-[220px] flex flex-col gap-y-2 fixed left-0 top-0 h-[100vh] bg-[#F9F9F9]">
|
||||||
<div>
|
<div>
|
||||||
<Logo />
|
<Logo />
|
||||||
</div>
|
</div>
|
||||||
<nav className="flex flex-col px-1">
|
<nav className="flex flex-col py-1">
|
||||||
{
|
{
|
||||||
linkList.map((item) => {
|
linkList.map((item) => {
|
||||||
return (
|
return (
|
||||||
|
@ -28,7 +30,11 @@ export default function SiderNav({ linkList }: { linkList: LinkType[] }) {
|
||||||
}
|
}
|
||||||
<span>{item.label}</span>
|
<span>{item.label}</span>
|
||||||
</Link> :
|
</Link> :
|
||||||
<div className="cursor-pointer py-3 flex gap-x-2 items-center hover:bg-[#E0E0E0] rounded pl-3 text-[#515C6B] hover:text-[#5961F9] text-[14px]" key={item._id}>
|
<div className="cursor-pointer py-3 flex gap-x-2 items-center hover:bg-[#E0E0E0] rounded pl-3 text-[#515C6B] hover:text-[#5961F9] text-[14px]" key={item._id}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectType(item._id)
|
||||||
|
}}
|
||||||
|
>
|
||||||
<img src={item.icon as string} className="w-[20px] h-[20px] object-cover"></img>
|
<img src={item.icon as string} className="w-[20px] h-[20px] object-cover"></img>
|
||||||
|
|
||||||
<span>{item.label}</span>
|
<span>{item.label}</span>
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
import { Button, Form, Input, message } from "antd";
|
|
||||||
import { useEffect } from "react";
|
|
||||||
import { mRequest } from "@/app/_lib/request";
|
|
||||||
|
|
||||||
export default function EditIconContent({
|
|
||||||
item,
|
|
||||||
onRefresh,
|
|
||||||
}: {
|
|
||||||
item: | null;
|
|
||||||
onRefresh: () => void;
|
|
||||||
}) {
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
console.log(item);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (item) {
|
|
||||||
form.setFieldsValue({ ...item });
|
|
||||||
} else {
|
|
||||||
form.resetFields();
|
|
||||||
}
|
|
||||||
}, [item, form]);
|
|
||||||
return (
|
|
||||||
<Form
|
|
||||||
layout="vertical"
|
|
||||||
form={form}
|
|
||||||
initialValues={{
|
|
||||||
// ...item,
|
|
||||||
// name: "",
|
|
||||||
// icons: [],
|
|
||||||
// link: "",
|
|
||||||
}}
|
|
||||||
onFinish={(res) => {
|
|
||||||
console.log(res);
|
|
||||||
mRequest(item ? "PUT" : "POST", "/app/linkIcon", {
|
|
||||||
data: item ? { id: item.id, ...res } : res,
|
|
||||||
returnType: "text",
|
|
||||||
}).then(() => {
|
|
||||||
message.success((item ? "修改" : "新增") + "成功");
|
|
||||||
onRefresh();
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Form.Item
|
|
||||||
label="名称"
|
|
||||||
name="name"
|
|
||||||
rules={[{ required: true, message: "名称必填" }]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
{
|
|
||||||
!item ?
|
|
||||||
<>
|
|
||||||
<Form.Item
|
|
||||||
label="链接名称"
|
|
||||||
name="linkName"
|
|
||||||
rules={[{ required: true, message: "链接必填" }]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label="链接标签"
|
|
||||||
name="linkTag"
|
|
||||||
rules={[{ required: true, message: "链接必填" }]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
</> : ''
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
<Form.Item className="flex justify-end">
|
|
||||||
<Button type="primary" htmlType="submit">
|
|
||||||
确认{item ? "修改" : "添加"}
|
|
||||||
</Button>
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { mRequest } from "@/app/_lib/request"
|
import { mRequest } from "@/app/_lib/request"
|
||||||
import ImageUpload from "@/app/_ui/ImageUpload"
|
import ImageUpload from "@/app/_ui/ImageUpload"
|
||||||
import { Link } from "@/app/api/link/route"
|
import { Link } from "@/app/api/link/route"
|
||||||
|
import { LinkType } from "@/app/api/linkType/route"
|
||||||
|
import { useRequest } from "ahooks"
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
|
@ -11,15 +13,22 @@ import {
|
||||||
message,
|
message,
|
||||||
Modal,
|
Modal,
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
|
Radio,
|
||||||
|
Select,
|
||||||
Space,
|
Space,
|
||||||
Table,
|
Table,
|
||||||
} from "antd"
|
} from "antd"
|
||||||
import { useCallback, useEffect, useState } from "react"
|
import { useCallback, useEffect, useState } from "react"
|
||||||
|
import useSWR from "swr"
|
||||||
|
|
||||||
|
|
||||||
export default function LinkTable(props: { id: string }) {
|
export default function LinkTable(props: { id: string }) {
|
||||||
const [list, setList] = useState<Link[]>([])
|
const [list, setList] = useState<Link[]>([])
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
const { data: LinkTypeList } = useRequest(async () => mRequest<{
|
||||||
|
list: LinkType[]
|
||||||
|
}>('GET', '/api/linkType'))
|
||||||
|
|
||||||
const refresh = useCallback(async () => {
|
const refresh = useCallback(async () => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
const res = await mRequest<{ list: Link[] }>(
|
const res = await mRequest<{ list: Link[] }>(
|
||||||
|
@ -68,7 +77,13 @@ export default function LinkTable(props: { id: string }) {
|
||||||
<Image width={80} src={row.logoLink}></Image>
|
<Image width={80} src={row.logoLink}></Image>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "是否热门",
|
||||||
|
dataIndex: "isHot",
|
||||||
|
render: (_, row) => (
|
||||||
|
row.isHot ? '是' : '否'
|
||||||
|
)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
fixed: "right",
|
fixed: "right",
|
||||||
|
@ -81,9 +96,7 @@ export default function LinkTable(props: { id: string }) {
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title="确认删除?"
|
title="确认删除?"
|
||||||
onConfirm={async () => {
|
onConfirm={async () => {
|
||||||
await mRequest("DELETE", "/app/link/" + row.id, {
|
await mRequest("DELETE", "/api/link/" + row._id,)
|
||||||
returnType: "text",
|
|
||||||
})
|
|
||||||
refresh()
|
refresh()
|
||||||
message.success("删除成功")
|
message.success("删除成功")
|
||||||
}}
|
}}
|
||||||
|
@ -110,12 +123,14 @@ export default function LinkTable(props: { id: string }) {
|
||||||
initialValues={
|
initialValues={
|
||||||
selected
|
selected
|
||||||
? selected
|
? selected
|
||||||
: { title: "", url: "", logoLink: "", description: "", priority: 0 }
|
: { title: "", url: "", logoLink: "", description: "", priority: 0, type: props.id }
|
||||||
}
|
}
|
||||||
onFinish={async (res) => {
|
onFinish={async (res) => {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
await mRequest("PUT", "/api/link", {
|
await mRequest("PUT", "/api/link", {
|
||||||
id: selected._id, ...res
|
_id: selected._id,
|
||||||
|
...res,
|
||||||
|
type: props.id
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
await mRequest("POST", "/api/link", {
|
await mRequest("POST", "/api/link", {
|
||||||
|
@ -134,6 +149,9 @@ export default function LinkTable(props: { id: string }) {
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item name="link" label="链接" rules={[{ required: true, message: "链接必填" }]}>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="logoLink"
|
name="logoLink"
|
||||||
label="图标名称"
|
label="图标名称"
|
||||||
|
@ -145,15 +163,38 @@ export default function LinkTable(props: { id: string }) {
|
||||||
height={60}
|
height={60}
|
||||||
></ImageUpload>
|
></ImageUpload>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="link" label="链接" rules={[{ required: true, message: "链接必填" }]}>
|
|
||||||
<Input />
|
<Form.Item name="description" label="详情"
|
||||||
</Form.Item>
|
rules={[{ required: true, message: "详情必填" }]}
|
||||||
<Form.Item name="description" label="详情" >
|
>
|
||||||
<Input.TextArea />
|
<Input.TextArea />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item name="type" label="分类"
|
||||||
|
rules={[{ required: true, message: "分类必填" }]}
|
||||||
|
|
||||||
|
>
|
||||||
|
<Select options={LinkTypeList?.list.map(item => ({
|
||||||
|
label: item.label,
|
||||||
|
value: item._id
|
||||||
|
}))}></Select>
|
||||||
|
</Form.Item>
|
||||||
<Form.Item name="priority" label="优先级">
|
<Form.Item name="priority" label="优先级">
|
||||||
<InputNumber></InputNumber>
|
<InputNumber></InputNumber>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item name="isHot" label="是否热门">
|
||||||
|
<Radio.Group
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: '是',
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '否',
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
<Form.Item className="flex justify-end">
|
<Form.Item className="flex justify-end">
|
||||||
<Button type="primary" htmlType="submit">
|
<Button type="primary" htmlType="submit">
|
||||||
确认
|
确认
|
||||||
|
@ -161,6 +202,6 @@ export default function LinkTable(props: { id: string }) {
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div >
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import ImageUpload from "@/app/_ui/ImageUpload";
|
||||||
import { useForm } from "antd/es/form/Form";
|
import { useForm } from "antd/es/form/Form";
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
|
const [form] = useForm()
|
||||||
const { tableProps, refresh } = useAntdTable(
|
const { tableProps, refresh } = useAntdTable(
|
||||||
async ({ current, pageSize }) => {
|
async ({ current, pageSize }) => {
|
||||||
return mRequest<{
|
return mRequest<{
|
||||||
|
@ -120,6 +121,7 @@ export default function Page() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Form
|
<Form
|
||||||
|
form={form}
|
||||||
labelCol={{ span: 4 }}
|
labelCol={{ span: 4 }}
|
||||||
initialValues={selectedType ?
|
initialValues={selectedType ?
|
||||||
selectedType
|
selectedType
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { getCollection, getDb } from "@/app/_lib/mongodb";
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
import { NextRequest } from "next/server";
|
||||||
|
import { Link } from "../route";
|
||||||
|
|
||||||
|
export async function GET(req: NextRequest) {
|
||||||
|
try {
|
||||||
|
const collection = await getCollection('link');
|
||||||
|
// Check if the user is authenticated
|
||||||
|
|
||||||
|
const page = parseInt(req.nextUrl.searchParams.get('page') || '1') || 1;
|
||||||
|
const pageSize = parseInt(req.nextUrl.searchParams.get('pageSize') || '10') || 10;
|
||||||
|
const typeId = req.nextUrl.searchParams.get('typeId')
|
||||||
|
// 计算起始索引和结束索引
|
||||||
|
const startIndex = (page - 1) * pageSize;
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
const cursor = collection.find<Link>({ type: typeId }).skip(startIndex).limit(pageSize);
|
||||||
|
const data = await cursor.toArray();
|
||||||
|
|
||||||
|
// 计算总数量
|
||||||
|
const total = (await collection.find<Link>({ type: typeId }).toArray()).length
|
||||||
|
|
||||||
|
return Response.json({
|
||||||
|
total,
|
||||||
|
list: data,
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
return Response.error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export async function DELETE(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||||
|
try {
|
||||||
|
// 获取路径参数
|
||||||
|
const slug = (await params).id
|
||||||
|
const collection = await getCollection('link')
|
||||||
|
collection.deleteOne({
|
||||||
|
_id: new ObjectId(slug)
|
||||||
|
})
|
||||||
|
return Response.json({ message: '删除成功' })
|
||||||
|
} catch (e) {
|
||||||
|
return Response.error()
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,13 +13,14 @@ export type Link = {
|
||||||
type: string;
|
type: string;
|
||||||
priority: number;
|
priority: number;
|
||||||
logoLink: string;
|
logoLink: string;
|
||||||
|
isHot?: boolean;
|
||||||
|
|
||||||
}
|
}
|
||||||
export async function GET(req: NextRequest) {
|
export async function GET(req: NextRequest) {
|
||||||
try {
|
try {
|
||||||
const collection = await getCollection('link');
|
const collection = await getCollection('link');
|
||||||
// Check if the user is authenticated
|
// Check if the user is authenticated
|
||||||
|
|
||||||
const page = parseInt(req.nextUrl.searchParams.get('page') || '1') || 1;
|
const page = parseInt(req.nextUrl.searchParams.get('page') || '1') || 1;
|
||||||
const pageSize = parseInt(req.nextUrl.searchParams.get('pageSize') || '10') || 10;
|
const pageSize = parseInt(req.nextUrl.searchParams.get('pageSize') || '10') || 10;
|
||||||
const typeId = req.nextUrl.searchParams.get('typeId')
|
const typeId = req.nextUrl.searchParams.get('typeId')
|
||||||
|
@ -52,26 +53,13 @@ export async function POST(req: NextRequest) {
|
||||||
return Response.error()
|
return Response.error()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function DELETE(req: NextRequest) {
|
|
||||||
try {
|
|
||||||
// 获取路径参数
|
|
||||||
const segments = req.nextUrl.pathname.split('/')
|
|
||||||
const dynamicParam = segments[segments.length - 1]
|
|
||||||
const collection = await getCollection('link')
|
|
||||||
collection.deleteOne({
|
|
||||||
_id: new ObjectId(dynamicParam)
|
|
||||||
})
|
|
||||||
return Response.json({ message: '删除成功' })
|
|
||||||
} catch (e) {
|
|
||||||
return Response.error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export async function PUT(req: NextRequest) {
|
export async function PUT(req: NextRequest) {
|
||||||
try {
|
try {
|
||||||
// 获取待更新的对象
|
// 获取待更新的对象
|
||||||
const link = await req.json() as Link
|
const link = await req.json() as Link
|
||||||
const collection = await getCollection('link')
|
const collection = await getCollection('link')
|
||||||
await collection.updateOne({ _id: new ObjectId(link.id) }, { $set: link })
|
await collection.replaceOne({ _id: new ObjectId(link._id) }, { ...link, _id: new ObjectId(link._id) })
|
||||||
return Response.json({ message: '成功' })
|
return Response.json({ message: '成功' })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Response.error()
|
return Response.error()
|
||||||
|
|
|
@ -9,6 +9,7 @@ export type LinkType = {
|
||||||
iconElement?: ReactNode;
|
iconElement?: ReactNode;
|
||||||
_id: string;
|
_id: string;
|
||||||
href?: string;
|
href?: string;
|
||||||
|
priority: number;
|
||||||
location?: string;
|
location?: string;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,13 @@
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"icons": "link:@awesome.me/kit-KIT_CODE/icons",
|
"icons": "link:@awesome.me/kit-KIT_CODE/icons",
|
||||||
"jose": "^5.9.6",
|
"jose": "^5.9.6",
|
||||||
|
"jotai": "^2.11.1",
|
||||||
"mongodb": "^6.12.0",
|
"mongodb": "^6.12.0",
|
||||||
"next": "15.1.4",
|
"next": "15.1.4",
|
||||||
"proxy-agent": "^6.5.0",
|
"proxy-agent": "^6.5.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
"swr": "^2.3.0",
|
||||||
"uuid": "^11.0.5",
|
"uuid": "^11.0.5",
|
||||||
"zod": "^3.24.1"
|
"zod": "^3.24.1"
|
||||||
},
|
},
|
||||||
|
|
|
@ -41,6 +41,9 @@ importers:
|
||||||
jose:
|
jose:
|
||||||
specifier: ^5.9.6
|
specifier: ^5.9.6
|
||||||
version: 5.9.6
|
version: 5.9.6
|
||||||
|
jotai:
|
||||||
|
specifier: ^2.11.1
|
||||||
|
version: 2.11.1(@types/react@19.0.7)(react@19.0.0)
|
||||||
mongodb:
|
mongodb:
|
||||||
specifier: ^6.12.0
|
specifier: ^6.12.0
|
||||||
version: 6.12.0(socks@2.8.3)
|
version: 6.12.0(socks@2.8.3)
|
||||||
|
@ -56,6 +59,9 @@ importers:
|
||||||
react-dom:
|
react-dom:
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.0.0(react@19.0.0)
|
version: 19.0.0(react@19.0.0)
|
||||||
|
swr:
|
||||||
|
specifier: ^2.3.0
|
||||||
|
version: 2.3.0(react@19.0.0)
|
||||||
uuid:
|
uuid:
|
||||||
specifier: ^11.0.5
|
specifier: ^11.0.5
|
||||||
version: 11.0.5
|
version: 11.0.5
|
||||||
|
@ -950,6 +956,10 @@ packages:
|
||||||
delegates@1.0.0:
|
delegates@1.0.0:
|
||||||
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
||||||
|
|
||||||
|
dequal@2.0.3:
|
||||||
|
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
destroy@1.2.0:
|
destroy@1.2.0:
|
||||||
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
||||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||||
|
@ -1524,6 +1534,18 @@ packages:
|
||||||
jose@5.9.6:
|
jose@5.9.6:
|
||||||
resolution: {integrity: sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==}
|
resolution: {integrity: sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==}
|
||||||
|
|
||||||
|
jotai@2.11.1:
|
||||||
|
resolution: {integrity: sha512-41Su098mpHIX29hF/XOpDb0SqF6EES7+HXfrhuBqVSzRkxX48hD5i8nGsEewWZNAsBWJCTTmuz8M946Ih2PfcQ==}
|
||||||
|
engines: {node: '>=12.20.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '>=17.0.0'
|
||||||
|
react: '>=17.0.0'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
|
||||||
js-base64@2.6.4:
|
js-base64@2.6.4:
|
||||||
resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==}
|
resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==}
|
||||||
|
|
||||||
|
@ -2500,6 +2522,11 @@ packages:
|
||||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
swr@2.3.0:
|
||||||
|
resolution: {integrity: sha512-NyZ76wA4yElZWBHzSgEJc28a0u6QZvhb6w0azeL2k7+Q1gAzVK+IqQYXhVOC/mzi+HZIozrZvBVeSeOZNR2bqA==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||||
|
|
||||||
tailwindcss@3.4.17:
|
tailwindcss@3.4.17:
|
||||||
resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
|
resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
@ -2607,6 +2634,11 @@ packages:
|
||||||
proxy-agent:
|
proxy-agent:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
use-sync-external-store@1.4.0:
|
||||||
|
resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||||
|
|
||||||
util-deprecate@1.0.2:
|
util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
|
|
||||||
|
@ -3632,6 +3664,8 @@ snapshots:
|
||||||
|
|
||||||
delegates@1.0.0: {}
|
delegates@1.0.0: {}
|
||||||
|
|
||||||
|
dequal@2.0.3: {}
|
||||||
|
|
||||||
destroy@1.2.0: {}
|
destroy@1.2.0: {}
|
||||||
|
|
||||||
detect-libc@2.0.3: {}
|
detect-libc@2.0.3: {}
|
||||||
|
@ -4393,6 +4427,11 @@ snapshots:
|
||||||
|
|
||||||
jose@5.9.6: {}
|
jose@5.9.6: {}
|
||||||
|
|
||||||
|
jotai@2.11.1(@types/react@19.0.7)(react@19.0.0):
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.0.7
|
||||||
|
react: 19.0.0
|
||||||
|
|
||||||
js-base64@2.6.4: {}
|
js-base64@2.6.4: {}
|
||||||
|
|
||||||
js-cookie@3.0.5: {}
|
js-cookie@3.0.5: {}
|
||||||
|
@ -5490,6 +5529,12 @@ snapshots:
|
||||||
|
|
||||||
supports-preserve-symlinks-flag@1.0.0: {}
|
supports-preserve-symlinks-flag@1.0.0: {}
|
||||||
|
|
||||||
|
swr@2.3.0(react@19.0.0):
|
||||||
|
dependencies:
|
||||||
|
dequal: 2.0.3
|
||||||
|
react: 19.0.0
|
||||||
|
use-sync-external-store: 1.4.0(react@19.0.0)
|
||||||
|
|
||||||
tailwindcss@3.4.17:
|
tailwindcss@3.4.17:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@alloc/quick-lru': 5.2.0
|
'@alloc/quick-lru': 5.2.0
|
||||||
|
@ -5642,6 +5687,10 @@ snapshots:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
proxy-agent: 6.5.0
|
proxy-agent: 6.5.0
|
||||||
|
|
||||||
|
use-sync-external-store@1.4.0(react@19.0.0):
|
||||||
|
dependencies:
|
||||||
|
react: 19.0.0
|
||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|
||||||
utility@1.18.0:
|
utility@1.18.0:
|
||||||
|
|
Loading…
Reference in New Issue