├── .gitignore
├── README.md
├── app
├── dashboard
│ ├── (overview)
│ │ ├── loading.tsx
│ │ └── page.tsx
│ ├── customers
│ │ └── page.tsx
│ ├── invoices
│ │ └── page.tsx
│ └── layout.tsx
├── layout.tsx
├── lib
│ ├── data.ts
│ ├── definitions.ts
│ ├── placeholder-data.ts
│ └── utils.ts
├── page.tsx
├── query
│ └── route.ts
├── seed
│ └── route.ts
└── ui
│ ├── acme-logo.tsx
│ ├── button.tsx
│ ├── customers
│ └── table.tsx
│ ├── dashboard
│ ├── cards.tsx
│ ├── latest-invoices.tsx
│ ├── nav-links.tsx
│ ├── revenue-chart.tsx
│ └── sidenav.tsx
│ ├── fonts.ts
│ ├── global.css
│ ├── invoices
│ ├── breadcrumbs.tsx
│ ├── buttons.tsx
│ ├── create-form.tsx
│ ├── edit-form.tsx
│ ├── pagination.tsx
│ ├── status.tsx
│ └── table.tsx
│ ├── login-form.tsx
│ ├── search.tsx
│ └── skeletons.tsx
├── next.config.ts
├── package.json
├── pnpm-lock.yaml
├── postcss.config.js
├── public
├── customers
│ ├── amy-burns.png
│ ├── balazs-orban.png
│ ├── delba-de-oliveira.png
│ ├── evil-rabbit.png
│ ├── lee-robinson.png
│ └── michael-novotny.png
├── favicon.ico
├── hero-desktop.png
├── hero-mobile.png
└── opengraph-image.png
├── tailwind.config.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
27 | # local env files
28 | .env*.local
29 | .env
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
38 | # idea
39 | .idea
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Next.js App Router Course - Starter
2 |
3 | This is the starter template for the Next.js App Router Course. It contains the starting code for the dashboard application.
4 |
5 | For more information, see the [course curriculum](https://nextjs.org/learn) on the Next.js Website.
6 |
--------------------------------------------------------------------------------
/app/dashboard/(overview)/loading.tsx:
--------------------------------------------------------------------------------
1 | import DashboardSkeleton from "@/app/ui/skeletons";
2 |
3 | const Loading = () => {
4 | return ;
5 | }
6 | export default Loading
7 |
--------------------------------------------------------------------------------
/app/dashboard/(overview)/page.tsx:
--------------------------------------------------------------------------------
1 | import CardWrapper from '@/app/ui/dashboard/cards';
2 | import RevenueChart from '@/app/ui/dashboard/revenue-chart';
3 | import LatestInvoices from '@/app/ui/dashboard/latest-invoices';
4 | import { lusitana } from '@/app/ui/fonts';
5 | import { Suspense } from 'react';
6 | import {CardSkeleton, CardsSkeleton, LatestInvoicesSkeleton, RevenueChartSkeleton} from "@/app/ui/skeletons";
7 |
8 | export default async function Page() {
9 |
10 | return (
11 |
12 |
13 | Dashboard
14 |
15 |
16 | }>
17 |
18 |
19 |
20 |
21 | }>
22 |
23 |
24 | }>
25 |
26 |
27 |
28 |
29 | );
30 | }
--------------------------------------------------------------------------------
/app/dashboard/customers/page.tsx:
--------------------------------------------------------------------------------
1 | const Page = () => {
2 | return
Customers Page
3 | }
4 | export default Page
5 |
--------------------------------------------------------------------------------
/app/dashboard/invoices/page.tsx:
--------------------------------------------------------------------------------
1 | const Page = () => {
2 | return Invoices Page
3 | }
4 | export default Page
5 |
--------------------------------------------------------------------------------
/app/dashboard/layout.tsx:
--------------------------------------------------------------------------------
1 | import SideNav from '@/app/ui/dashboard/sidenav';
2 |
3 | export default function Layout({ children }: { children: React.ReactNode }) {
4 | return (
5 |
6 |
7 |
8 |
9 |
{children}
10 |
11 | );
12 | }
--------------------------------------------------------------------------------
/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import '@/app/ui/global.css'
2 | import {inter} from "@/app/ui/fonts";
3 |
4 | export default function RootLayout({
5 | children,
6 | }: {
7 | children: React.ReactNode;
8 | }) {
9 | return (
10 |
11 | {children}
12 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/app/lib/data.ts:
--------------------------------------------------------------------------------
1 | import postgres from 'postgres';
2 | import {
3 | CustomerField,
4 | CustomersTableType,
5 | InvoiceForm,
6 | InvoicesTable,
7 | LatestInvoiceRaw,
8 | Revenue,
9 | } from './definitions';
10 | import { formatCurrency } from './utils';
11 |
12 | const sql = postgres(process.env.POSTGRES_URL!, { ssl: 'require' });
13 |
14 | export async function fetchRevenue() {
15 | try {
16 | // Artificially delay a response for demo purposes.
17 | // Don't do this in production :)
18 |
19 | console.log('Fetching revenue data...');
20 | await new Promise((resolve) => setTimeout(resolve, 3000));
21 |
22 | const data = await sql`SELECT * FROM revenue`;
23 |
24 | console.log('Data fetch completed after 3 seconds.');
25 |
26 | return data;
27 | } catch (error) {
28 | console.error('Database Error:', error);
29 | throw new Error('Failed to fetch revenue data.');
30 | }
31 | }
32 |
33 | export async function fetchLatestInvoices() {
34 | try {
35 | const data = await sql`
36 | SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id
37 | FROM invoices
38 | JOIN customers ON invoices.customer_id = customers.id
39 | ORDER BY invoices.date DESC
40 | LIMIT 5`;
41 |
42 | const latestInvoices = data.map((invoice) => ({
43 | ...invoice,
44 | amount: formatCurrency(invoice.amount),
45 | }));
46 | return latestInvoices;
47 | } catch (error) {
48 | console.error('Database Error:', error);
49 | throw new Error('Failed to fetch the latest invoices.');
50 | }
51 | }
52 |
53 | export async function fetchCardData() {
54 | try {
55 | // You can probably combine these into a single SQL query
56 | // However, we are intentionally splitting them to demonstrate
57 | // how to initialize multiple queries in parallel with JS.
58 | const invoiceCountPromise = sql`SELECT COUNT(*) FROM invoices`;
59 | const customerCountPromise = sql`SELECT COUNT(*) FROM customers`;
60 | const invoiceStatusPromise = sql`SELECT
61 | SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) AS "paid",
62 | SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) AS "pending"
63 | FROM invoices`;
64 |
65 | const data = await Promise.all([
66 | invoiceCountPromise,
67 | customerCountPromise,
68 | invoiceStatusPromise,
69 | ]);
70 |
71 | const numberOfInvoices = Number(data[0].count ?? '0');
72 | const numberOfCustomers = Number(data[1].count ?? '0');
73 | const totalPaidInvoices = formatCurrency(data[2][0].paid ?? '0');
74 | const totalPendingInvoices = formatCurrency(data[2][0].pending ?? '0');
75 |
76 | return {
77 | numberOfCustomers,
78 | numberOfInvoices,
79 | totalPaidInvoices,
80 | totalPendingInvoices,
81 | };
82 | } catch (error) {
83 | console.error('Database Error:', error);
84 | throw new Error('Failed to fetch card data.');
85 | }
86 | }
87 |
88 | const ITEMS_PER_PAGE = 6;
89 | export async function fetchFilteredInvoices(
90 | query: string,
91 | currentPage: number,
92 | ) {
93 | const offset = (currentPage - 1) * ITEMS_PER_PAGE;
94 |
95 | try {
96 | const invoices = await sql`
97 | SELECT
98 | invoices.id,
99 | invoices.amount,
100 | invoices.date,
101 | invoices.status,
102 | customers.name,
103 | customers.email,
104 | customers.image_url
105 | FROM invoices
106 | JOIN customers ON invoices.customer_id = customers.id
107 | WHERE
108 | customers.name ILIKE ${`%${query}%`} OR
109 | customers.email ILIKE ${`%${query}%`} OR
110 | invoices.amount::text ILIKE ${`%${query}%`} OR
111 | invoices.date::text ILIKE ${`%${query}%`} OR
112 | invoices.status ILIKE ${`%${query}%`}
113 | ORDER BY invoices.date DESC
114 | LIMIT ${ITEMS_PER_PAGE} OFFSET ${offset}
115 | `;
116 |
117 | return invoices;
118 | } catch (error) {
119 | console.error('Database Error:', error);
120 | throw new Error('Failed to fetch invoices.');
121 | }
122 | }
123 |
124 | export async function fetchInvoicesPages(query: string) {
125 | try {
126 | const data = await sql`SELECT COUNT(*)
127 | FROM invoices
128 | JOIN customers ON invoices.customer_id = customers.id
129 | WHERE
130 | customers.name ILIKE ${`%${query}%`} OR
131 | customers.email ILIKE ${`%${query}%`} OR
132 | invoices.amount::text ILIKE ${`%${query}%`} OR
133 | invoices.date::text ILIKE ${`%${query}%`} OR
134 | invoices.status ILIKE ${`%${query}%`}
135 | `;
136 |
137 | const totalPages = Math.ceil(Number(data[0].count) / ITEMS_PER_PAGE);
138 | return totalPages;
139 | } catch (error) {
140 | console.error('Database Error:', error);
141 | throw new Error('Failed to fetch total number of invoices.');
142 | }
143 | }
144 |
145 | export async function fetchInvoiceById(id: string) {
146 | try {
147 | const data = await sql`
148 | SELECT
149 | invoices.id,
150 | invoices.customer_id,
151 | invoices.amount,
152 | invoices.status
153 | FROM invoices
154 | WHERE invoices.id = ${id};
155 | `;
156 |
157 | const invoice = data.map((invoice) => ({
158 | ...invoice,
159 | // Convert amount from cents to dollars
160 | amount: invoice.amount / 100,
161 | }));
162 |
163 | return invoice[0];
164 | } catch (error) {
165 | console.error('Database Error:', error);
166 | throw new Error('Failed to fetch invoice.');
167 | }
168 | }
169 |
170 | export async function fetchCustomers() {
171 | try {
172 | const customers = await sql`
173 | SELECT
174 | id,
175 | name
176 | FROM customers
177 | ORDER BY name ASC
178 | `;
179 |
180 | return customers;
181 | } catch (err) {
182 | console.error('Database Error:', err);
183 | throw new Error('Failed to fetch all customers.');
184 | }
185 | }
186 |
187 | export async function fetchFilteredCustomers(query: string) {
188 | try {
189 | const data = await sql`
190 | SELECT
191 | customers.id,
192 | customers.name,
193 | customers.email,
194 | customers.image_url,
195 | COUNT(invoices.id) AS total_invoices,
196 | SUM(CASE WHEN invoices.status = 'pending' THEN invoices.amount ELSE 0 END) AS total_pending,
197 | SUM(CASE WHEN invoices.status = 'paid' THEN invoices.amount ELSE 0 END) AS total_paid
198 | FROM customers
199 | LEFT JOIN invoices ON customers.id = invoices.customer_id
200 | WHERE
201 | customers.name ILIKE ${`%${query}%`} OR
202 | customers.email ILIKE ${`%${query}%`}
203 | GROUP BY customers.id, customers.name, customers.email, customers.image_url
204 | ORDER BY customers.name ASC
205 | `;
206 |
207 | const customers = data.map((customer) => ({
208 | ...customer,
209 | total_pending: formatCurrency(customer.total_pending),
210 | total_paid: formatCurrency(customer.total_paid),
211 | }));
212 |
213 | return customers;
214 | } catch (err) {
215 | console.error('Database Error:', err);
216 | throw new Error('Failed to fetch customer table.');
217 | }
218 | }
219 |
--------------------------------------------------------------------------------
/app/lib/definitions.ts:
--------------------------------------------------------------------------------
1 | // This file contains type definitions for your data.
2 | // It describes the shape of the data, and what data type each property should accept.
3 | // For simplicity of teaching, we're manually defining these types.
4 | // However, these types are generated automatically if you're using an ORM such as Prisma.
5 | export type User = {
6 | id: string;
7 | name: string;
8 | email: string;
9 | password: string;
10 | };
11 |
12 | export type Customer = {
13 | id: string;
14 | name: string;
15 | email: string;
16 | image_url: string;
17 | };
18 |
19 | export type Invoice = {
20 | id: string;
21 | customer_id: string;
22 | amount: number;
23 | date: string;
24 | // In TypeScript, this is called a string union type.
25 | // It means that the "status" property can only be one of the two strings: 'pending' or 'paid'.
26 | status: 'pending' | 'paid';
27 | };
28 |
29 | export type Revenue = {
30 | month: string;
31 | revenue: number;
32 | };
33 |
34 | export type LatestInvoice = {
35 | id: string;
36 | name: string;
37 | image_url: string;
38 | email: string;
39 | amount: string;
40 | };
41 |
42 | // The database returns a number for amount, but we later format it to a string with the formatCurrency function
43 | export type LatestInvoiceRaw = Omit & {
44 | amount: number;
45 | };
46 |
47 | export type InvoicesTable = {
48 | id: string;
49 | customer_id: string;
50 | name: string;
51 | email: string;
52 | image_url: string;
53 | date: string;
54 | amount: number;
55 | status: 'pending' | 'paid';
56 | };
57 |
58 | export type CustomersTableType = {
59 | id: string;
60 | name: string;
61 | email: string;
62 | image_url: string;
63 | total_invoices: number;
64 | total_pending: number;
65 | total_paid: number;
66 | };
67 |
68 | export type FormattedCustomersTable = {
69 | id: string;
70 | name: string;
71 | email: string;
72 | image_url: string;
73 | total_invoices: number;
74 | total_pending: string;
75 | total_paid: string;
76 | };
77 |
78 | export type CustomerField = {
79 | id: string;
80 | name: string;
81 | };
82 |
83 | export type InvoiceForm = {
84 | id: string;
85 | customer_id: string;
86 | amount: number;
87 | status: 'pending' | 'paid';
88 | };
89 |
--------------------------------------------------------------------------------
/app/lib/placeholder-data.ts:
--------------------------------------------------------------------------------
1 | // This file contains placeholder data that you'll be replacing with real data in the Data Fetching chapter:
2 | // https://nextjs.org/learn/dashboard-app/fetching-data
3 | const users = [
4 | {
5 | id: '410544b2-4001-4271-9855-fec4b6a6442a',
6 | name: 'User',
7 | email: 'user@nextmail.com',
8 | password: '123456',
9 | },
10 | ];
11 |
12 | const customers = [
13 | {
14 | id: 'd6e15727-9fe1-4961-8c5b-ea44a9bd81aa',
15 | name: 'Evil Rabbit',
16 | email: 'evil@rabbit.com',
17 | image_url: '/customers/evil-rabbit.png',
18 | },
19 | {
20 | id: '3958dc9e-712f-4377-85e9-fec4b6a6442a',
21 | name: 'Delba de Oliveira',
22 | email: 'delba@oliveira.com',
23 | image_url: '/customers/delba-de-oliveira.png',
24 | },
25 | {
26 | id: '3958dc9e-742f-4377-85e9-fec4b6a6442a',
27 | name: 'Lee Robinson',
28 | email: 'lee@robinson.com',
29 | image_url: '/customers/lee-robinson.png',
30 | },
31 | {
32 | id: '76d65c26-f784-44a2-ac19-586678f7c2f2',
33 | name: 'Michael Novotny',
34 | email: 'michael@novotny.com',
35 | image_url: '/customers/michael-novotny.png',
36 | },
37 | {
38 | id: 'CC27C14A-0ACF-4F4A-A6C9-D45682C144B9',
39 | name: 'Amy Burns',
40 | email: 'amy@burns.com',
41 | image_url: '/customers/amy-burns.png',
42 | },
43 | {
44 | id: '13D07535-C59E-4157-A011-F8D2EF4E0CBB',
45 | name: 'Balazs Orban',
46 | email: 'balazs@orban.com',
47 | image_url: '/customers/balazs-orban.png',
48 | },
49 | ];
50 |
51 | const invoices = [
52 | {
53 | customer_id: customers[0].id,
54 | amount: 15795,
55 | status: 'pending',
56 | date: '2022-12-06',
57 | },
58 | {
59 | customer_id: customers[1].id,
60 | amount: 20348,
61 | status: 'pending',
62 | date: '2022-11-14',
63 | },
64 | {
65 | customer_id: customers[4].id,
66 | amount: 3040,
67 | status: 'paid',
68 | date: '2022-10-29',
69 | },
70 | {
71 | customer_id: customers[3].id,
72 | amount: 44800,
73 | status: 'paid',
74 | date: '2023-09-10',
75 | },
76 | {
77 | customer_id: customers[5].id,
78 | amount: 34577,
79 | status: 'pending',
80 | date: '2023-08-05',
81 | },
82 | {
83 | customer_id: customers[2].id,
84 | amount: 54246,
85 | status: 'pending',
86 | date: '2023-07-16',
87 | },
88 | {
89 | customer_id: customers[0].id,
90 | amount: 666,
91 | status: 'pending',
92 | date: '2023-06-27',
93 | },
94 | {
95 | customer_id: customers[3].id,
96 | amount: 32545,
97 | status: 'paid',
98 | date: '2023-06-09',
99 | },
100 | {
101 | customer_id: customers[4].id,
102 | amount: 1250,
103 | status: 'paid',
104 | date: '2023-06-17',
105 | },
106 | {
107 | customer_id: customers[5].id,
108 | amount: 8546,
109 | status: 'paid',
110 | date: '2023-06-07',
111 | },
112 | {
113 | customer_id: customers[1].id,
114 | amount: 500,
115 | status: 'paid',
116 | date: '2023-08-19',
117 | },
118 | {
119 | customer_id: customers[5].id,
120 | amount: 8945,
121 | status: 'paid',
122 | date: '2023-06-03',
123 | },
124 | {
125 | customer_id: customers[2].id,
126 | amount: 1000,
127 | status: 'paid',
128 | date: '2022-06-05',
129 | },
130 | ];
131 |
132 | const revenue = [
133 | { month: 'Jan', revenue: 2000 },
134 | { month: 'Feb', revenue: 1800 },
135 | { month: 'Mar', revenue: 2200 },
136 | { month: 'Apr', revenue: 2500 },
137 | { month: 'May', revenue: 2300 },
138 | { month: 'Jun', revenue: 3200 },
139 | { month: 'Jul', revenue: 3500 },
140 | { month: 'Aug', revenue: 3700 },
141 | { month: 'Sep', revenue: 2500 },
142 | { month: 'Oct', revenue: 2800 },
143 | { month: 'Nov', revenue: 3000 },
144 | { month: 'Dec', revenue: 4800 },
145 | ];
146 |
147 | export { users, customers, invoices, revenue };
148 |
--------------------------------------------------------------------------------
/app/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { Revenue } from './definitions';
2 |
3 | export const formatCurrency = (amount: number) => {
4 | return (amount / 100).toLocaleString('en-US', {
5 | style: 'currency',
6 | currency: 'USD',
7 | });
8 | };
9 |
10 | export const formatDateToLocal = (
11 | dateStr: string,
12 | locale: string = 'en-US',
13 | ) => {
14 | const date = new Date(dateStr);
15 | const options: Intl.DateTimeFormatOptions = {
16 | day: 'numeric',
17 | month: 'short',
18 | year: 'numeric',
19 | };
20 | const formatter = new Intl.DateTimeFormat(locale, options);
21 | return formatter.format(date);
22 | };
23 |
24 | export const generateYAxis = (revenue: Revenue[]) => {
25 | // Calculate what labels we need to display on the y-axis
26 | // based on highest record and in 1000s
27 | const yAxisLabels = [];
28 | const highestRecord = Math.max(...revenue.map((month) => month.revenue));
29 | const topLabel = Math.ceil(highestRecord / 1000) * 1000;
30 |
31 | for (let i = topLabel; i >= 0; i -= 1000) {
32 | yAxisLabels.push(`$${i / 1000}K`);
33 | }
34 |
35 | return { yAxisLabels, topLabel };
36 | };
37 |
38 | export const generatePagination = (currentPage: number, totalPages: number) => {
39 | // If the total number of pages is 7 or less,
40 | // display all pages without any ellipsis.
41 | if (totalPages <= 7) {
42 | return Array.from({ length: totalPages }, (_, i) => i + 1);
43 | }
44 |
45 | // If the current page is among the first 3 pages,
46 | // show the first 3, an ellipsis, and the last 2 pages.
47 | if (currentPage <= 3) {
48 | return [1, 2, 3, '...', totalPages - 1, totalPages];
49 | }
50 |
51 | // If the current page is among the last 3 pages,
52 | // show the first 2, an ellipsis, and the last 3 pages.
53 | if (currentPage >= totalPages - 2) {
54 | return [1, 2, '...', totalPages - 2, totalPages - 1, totalPages];
55 | }
56 |
57 | // If the current page is somewhere in the middle,
58 | // show the first page, an ellipsis, the current page and its neighbors,
59 | // another ellipsis, and the last page.
60 | return [
61 | 1,
62 | '...',
63 | currentPage - 1,
64 | currentPage,
65 | currentPage + 1,
66 | '...',
67 | totalPages,
68 | ];
69 | };
70 |
--------------------------------------------------------------------------------
/app/page.tsx:
--------------------------------------------------------------------------------
1 | import AcmeLogo from '@/app/ui/acme-logo';
2 | import { ArrowRightIcon } from '@heroicons/react/24/outline';
3 | import Link from 'next/link';
4 | import Image from "next/image";
5 |
6 | export default function Page() {
7 | return (
8 |
9 |
12 |
13 |
14 |
17 |
18 | Welcome to Acme. This is the example for the{' '}
19 |
20 | Next.js Learn Course
21 |
22 | , brought to you by Vercel.
23 |
24 |
28 |
Log in
29 |
30 |
31 |
32 | {/* Add Hero Images Here */}
33 |
39 |
45 |
46 |
47 |
48 | );
49 | }
50 |
--------------------------------------------------------------------------------
/app/query/route.ts:
--------------------------------------------------------------------------------
1 | import postgres from 'postgres';
2 |
3 | const sql = postgres(process.env.POSTGRES_URL!, { ssl: 'require' });
4 |
5 | async function listInvoices() {
6 | const data = await sql`
7 | SELECT invoices.amount, customers.name
8 | FROM invoices
9 | JOIN customers ON invoices.customer_id = customers.id
10 | WHERE invoices.amount = 666;
11 | `;
12 |
13 | return data;
14 | }
15 |
16 | export async function GET() {
17 | try {
18 | return Response.json(await listInvoices());
19 | } catch (error) {
20 | return Response.json({ error }, { status: 500 });
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/seed/route.ts:
--------------------------------------------------------------------------------
1 | import bcrypt from 'bcrypt';
2 | import postgres from 'postgres';
3 | import { invoices, customers, revenue, users } from '../lib/placeholder-data';
4 |
5 | const sql = postgres(process.env.POSTGRES_URL!, { ssl: 'require' });
6 |
7 | async function seedUsers() {
8 | await sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`;
9 | await sql`
10 | CREATE TABLE IF NOT EXISTS users (
11 | id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
12 | name VARCHAR(255) NOT NULL,
13 | email TEXT NOT NULL UNIQUE,
14 | password TEXT NOT NULL
15 | );
16 | `;
17 |
18 | const insertedUsers = await Promise.all(
19 | users.map(async (user) => {
20 | const hashedPassword = await bcrypt.hash(user.password, 10);
21 | return sql`
22 | INSERT INTO users (id, name, email, password)
23 | VALUES (${user.id}, ${user.name}, ${user.email}, ${hashedPassword})
24 | ON CONFLICT (id) DO NOTHING;
25 | `;
26 | }),
27 | );
28 |
29 | return insertedUsers;
30 | }
31 |
32 | async function seedInvoices() {
33 | await sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`;
34 |
35 | await sql`
36 | CREATE TABLE IF NOT EXISTS invoices (
37 | id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
38 | customer_id UUID NOT NULL,
39 | amount INT NOT NULL,
40 | status VARCHAR(255) NOT NULL,
41 | date DATE NOT NULL
42 | );
43 | `;
44 |
45 | const insertedInvoices = await Promise.all(
46 | invoices.map(
47 | (invoice) => sql`
48 | INSERT INTO invoices (customer_id, amount, status, date)
49 | VALUES (${invoice.customer_id}, ${invoice.amount}, ${invoice.status}, ${invoice.date})
50 | ON CONFLICT (id) DO NOTHING;
51 | `,
52 | ),
53 | );
54 |
55 | return insertedInvoices;
56 | }
57 |
58 | async function seedCustomers() {
59 | await sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`;
60 |
61 | await sql`
62 | CREATE TABLE IF NOT EXISTS customers (
63 | id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
64 | name VARCHAR(255) NOT NULL,
65 | email VARCHAR(255) NOT NULL,
66 | image_url VARCHAR(255) NOT NULL
67 | );
68 | `;
69 |
70 | const insertedCustomers = await Promise.all(
71 | customers.map(
72 | (customer) => sql`
73 | INSERT INTO customers (id, name, email, image_url)
74 | VALUES (${customer.id}, ${customer.name}, ${customer.email}, ${customer.image_url})
75 | ON CONFLICT (id) DO NOTHING;
76 | `,
77 | ),
78 | );
79 |
80 | return insertedCustomers;
81 | }
82 |
83 | async function seedRevenue() {
84 | await sql`
85 | CREATE TABLE IF NOT EXISTS revenue (
86 | month VARCHAR(4) NOT NULL UNIQUE,
87 | revenue INT NOT NULL
88 | );
89 | `;
90 |
91 | const insertedRevenue = await Promise.all(
92 | revenue.map(
93 | (rev) => sql`
94 | INSERT INTO revenue (month, revenue)
95 | VALUES (${rev.month}, ${rev.revenue})
96 | ON CONFLICT (month) DO NOTHING;
97 | `,
98 | ),
99 | );
100 |
101 | return insertedRevenue;
102 | }
103 |
104 | export async function GET() {
105 | try {
106 | const result = await sql.begin((sql) => [
107 | seedUsers(),
108 | seedCustomers(),
109 | seedInvoices(),
110 | seedRevenue(),
111 | ]);
112 |
113 | return Response.json({ message: 'Database seeded successfully' });
114 | } catch (error) {
115 | return Response.json({ error }, { status: 500 });
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/app/ui/acme-logo.tsx:
--------------------------------------------------------------------------------
1 | import { GlobeAltIcon } from '@heroicons/react/24/outline';
2 | import { lusitana } from '@/app/ui/fonts';
3 |
4 | export default function AcmeLogo() {
5 | return (
6 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/app/ui/button.tsx:
--------------------------------------------------------------------------------
1 | import clsx from 'clsx';
2 |
3 | interface ButtonProps extends React.ButtonHTMLAttributes {
4 | children: React.ReactNode;
5 | }
6 |
7 | export function Button({ children, className, ...rest }: ButtonProps) {
8 | return (
9 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/app/ui/customers/table.tsx:
--------------------------------------------------------------------------------
1 | import Image from 'next/image';
2 | import { lusitana } from '@/app/ui/fonts';
3 | import Search from '@/app/ui/search';
4 | import {
5 | CustomersTableType,
6 | FormattedCustomersTable,
7 | } from '@/app/lib/definitions';
8 |
9 | export default async function CustomersTable({
10 | customers,
11 | }: {
12 | customers: FormattedCustomersTable[];
13 | }) {
14 | return (
15 |
16 |
17 | Customers
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | {customers?.map((customer) => (
26 |
30 |
31 |
32 |
33 |
34 |
41 |
{customer.name}
42 |
43 |
44 |
45 | {customer.email}
46 |
47 |
48 |
49 |
50 |
51 |
Pending
52 |
{customer.total_pending}
53 |
54 |
55 |
Paid
56 |
{customer.total_paid}
57 |
58 |
59 |
60 |
{customer.total_invoices} invoices
61 |
62 |
63 | ))}
64 |
65 |
66 |
67 |
68 |
69 | Name
70 | |
71 |
72 | Email
73 | |
74 |
75 | Total Invoices
76 | |
77 |
78 | Total Pending
79 | |
80 |
81 | Total Paid
82 | |
83 |
84 |
85 |
86 |
87 | {customers.map((customer) => (
88 |
89 |
90 |
91 |
98 | {customer.name}
99 |
100 | |
101 |
102 | {customer.email}
103 | |
104 |
105 | {customer.total_invoices}
106 | |
107 |
108 | {customer.total_pending}
109 | |
110 |
111 | {customer.total_paid}
112 | |
113 |
114 | ))}
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | );
123 | }
124 |
--------------------------------------------------------------------------------
/app/ui/dashboard/cards.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | BanknotesIcon,
3 | ClockIcon,
4 | UserGroupIcon,
5 | InboxIcon,
6 | } from '@heroicons/react/24/outline';
7 | import { lusitana } from '@/app/ui/fonts';
8 | import {fetchCardData} from "@/app/lib/data";
9 |
10 | const iconMap = {
11 | collected: BanknotesIcon,
12 | customers: UserGroupIcon,
13 | pending: ClockIcon,
14 | invoices: InboxIcon,
15 | };
16 |
17 | export default async function CardWrapper() {
18 | const { numberOfCustomers, numberOfInvoices, totalPaidInvoices, totalPendingInvoices } = await fetchCardData();
19 | return (
20 | <>
21 | {/* NOTE: Uncomment this code in Chapter 9 */}
22 |
23 |
24 |
25 |
26 |
31 | >
32 | );
33 | }
34 |
35 | export function Card({
36 | title,
37 | value,
38 | type,
39 | }: {
40 | title: string;
41 | value: number | string;
42 | type: 'invoices' | 'customers' | 'pending' | 'collected';
43 | }) {
44 | const Icon = iconMap[type];
45 |
46 | return (
47 |
48 |
49 | {Icon ? : null}
50 |
{title}
51 |
52 |
56 | {value}
57 |
58 |
59 | );
60 | }
61 |
--------------------------------------------------------------------------------
/app/ui/dashboard/latest-invoices.tsx:
--------------------------------------------------------------------------------
1 | import { ArrowPathIcon } from '@heroicons/react/24/outline';
2 | import clsx from 'clsx';
3 | import Image from 'next/image';
4 | import { lusitana } from '@/app/ui/fonts';
5 | import { LatestInvoice } from '@/app/lib/definitions';
6 | import { fetchLatestInvoices } from '@/app/lib/data';
7 |
8 | export default async function LatestInvoices() {
9 | const latestInvoices = await fetchLatestInvoices();
10 |
11 | return (
12 |
13 |
14 | Latest Invoices
15 |
16 |
17 | {/* NOTE: Uncomment this code in Chapter 7 */}
18 |
19 |
20 | {latestInvoices.map((invoice, i) => {
21 | return (
22 |
31 |
32 |
39 |
40 |
41 | {invoice.name}
42 |
43 |
44 | {invoice.email}
45 |
46 |
47 |
48 |
51 | {invoice.amount}
52 |
53 |
54 | );
55 | })}
56 |
57 |
58 |
59 |
Updated just now
60 |
61 |
62 |
63 | );
64 | }
65 |
--------------------------------------------------------------------------------
/app/ui/dashboard/nav-links.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import {
4 | UserGroupIcon,
5 | HomeIcon,
6 | DocumentDuplicateIcon,
7 | } from '@heroicons/react/24/outline';
8 | import Link from "next/link";
9 | import { usePathname } from "next/navigation";
10 | import clsx from "clsx";
11 |
12 | // Map of links to display in the side navigation.
13 | // Depending on the size of the application, this would be stored in a database.
14 | const links = [
15 | { name: 'Home', href: '/dashboard', icon: HomeIcon },
16 | {
17 | name: 'Invoices',
18 | href: '/dashboard/invoices',
19 | icon: DocumentDuplicateIcon,
20 | },
21 | { name: 'Customers', href: '/dashboard/customers', icon: UserGroupIcon },
22 | ];
23 |
24 | export default function NavLinks() {
25 | const pathname = usePathname();
26 |
27 | return (
28 | <>
29 | {links.map((link) => {
30 | const LinkIcon = link.icon;
31 | return (
32 |
41 |
42 | {link.name}
43 |
44 | );
45 | })}
46 | >
47 | );
48 | }
49 |
--------------------------------------------------------------------------------
/app/ui/dashboard/revenue-chart.tsx:
--------------------------------------------------------------------------------
1 | import { generateYAxis } from '@/app/lib/utils';
2 | import { CalendarIcon } from '@heroicons/react/24/outline';
3 | import { lusitana } from '@/app/ui/fonts';
4 | import { Revenue } from '@/app/lib/definitions';
5 | import { fetchRevenue } from "@/app/lib/data";
6 |
7 | // This component is representational only.
8 | // For data visualization UI, check out:
9 | // https://www.tremor.so/
10 | // https://www.chartjs.org/
11 | // https://airbnb.io/visx/
12 |
13 | export default async function RevenueChart() {
14 | const revenue = await fetchRevenue();
15 |
16 | const chartHeight = 350;
17 | // NOTE: Uncomment this code in Chapter 7
18 |
19 | const { yAxisLabels, topLabel } = generateYAxis(revenue);
20 |
21 | if (!revenue || revenue.length === 0) {
22 | return No data available.
;
23 | }
24 |
25 | return (
26 |
27 |
28 | Recent Revenue
29 |
30 | {/* NOTE: Uncomment this code in Chapter 7 */}
31 |
32 |
33 |
34 |
38 | {yAxisLabels.map((label) => (
39 |
{label}
40 | ))}
41 |
42 |
43 | {revenue.map((month) => (
44 |
45 |
51 |
52 | {month.month}
53 |
54 |
55 | ))}
56 |
57 |
58 |
59 |
Last 12 months
60 |
61 |
62 |
63 | );
64 | }
65 |
--------------------------------------------------------------------------------
/app/ui/dashboard/sidenav.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link';
2 | import NavLinks from '@/app/ui/dashboard/nav-links';
3 | import AcmeLogo from '@/app/ui/acme-logo';
4 | import { PowerIcon } from '@heroicons/react/24/outline';
5 |
6 | export default function SideNav() {
7 | return (
8 |
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/app/ui/fonts.ts:
--------------------------------------------------------------------------------
1 | import { Inter, Lusitana } from 'next/font/google';
2 |
3 | export const inter = Inter({ subsets: ['latin'] });
4 | export const lusitana = Lusitana({
5 | weight: ['400', '700'],
6 | subsets: ['latin'],
7 | })
--------------------------------------------------------------------------------
/app/ui/global.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | input[type='number'] {
6 | -moz-appearance: textfield;
7 | appearance: textfield;
8 | }
9 |
10 | input[type='number']::-webkit-inner-spin-button {
11 | -webkit-appearance: none;
12 | margin: 0;
13 | }
14 |
15 | input[type='number']::-webkit-outer-spin-button {
16 | -webkit-appearance: none;
17 | margin: 0;
18 | }
19 |
--------------------------------------------------------------------------------
/app/ui/invoices/breadcrumbs.tsx:
--------------------------------------------------------------------------------
1 | import { clsx } from 'clsx';
2 | import Link from 'next/link';
3 | import { lusitana } from '@/app/ui/fonts';
4 |
5 | interface Breadcrumb {
6 | label: string;
7 | href: string;
8 | active?: boolean;
9 | }
10 |
11 | export default function Breadcrumbs({
12 | breadcrumbs,
13 | }: {
14 | breadcrumbs: Breadcrumb[];
15 | }) {
16 | return (
17 |
35 | );
36 | }
37 |
--------------------------------------------------------------------------------
/app/ui/invoices/buttons.tsx:
--------------------------------------------------------------------------------
1 | import { PencilIcon, PlusIcon, TrashIcon } from '@heroicons/react/24/outline';
2 | import Link from 'next/link';
3 |
4 | export function CreateInvoice() {
5 | return (
6 |
10 | Create Invoice{' '}
11 |
12 |
13 | );
14 | }
15 |
16 | export function UpdateInvoice({ id }: { id: string }) {
17 | return (
18 |
22 |
23 |
24 | );
25 | }
26 |
27 | export function DeleteInvoice({ id }: { id: string }) {
28 | return (
29 | <>
30 |
34 | >
35 | );
36 | }
37 |
--------------------------------------------------------------------------------
/app/ui/invoices/create-form.tsx:
--------------------------------------------------------------------------------
1 | import { CustomerField } from '@/app/lib/definitions';
2 | import Link from 'next/link';
3 | import {
4 | CheckIcon,
5 | ClockIcon,
6 | CurrencyDollarIcon,
7 | UserCircleIcon,
8 | } from '@heroicons/react/24/outline';
9 | import { Button } from '@/app/ui/button';
10 |
11 | export default function Form({ customers }: { customers: CustomerField[] }) {
12 | return (
13 |
111 | );
112 | }
113 |
--------------------------------------------------------------------------------
/app/ui/invoices/edit-form.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import { CustomerField, InvoiceForm } from '@/app/lib/definitions';
4 | import {
5 | CheckIcon,
6 | ClockIcon,
7 | CurrencyDollarIcon,
8 | UserCircleIcon,
9 | } from '@heroicons/react/24/outline';
10 | import Link from 'next/link';
11 | import { Button } from '@/app/ui/button';
12 |
13 | export default function EditInvoiceForm({
14 | invoice,
15 | customers,
16 | }: {
17 | invoice: InvoiceForm;
18 | customers: CustomerField[];
19 | }) {
20 | return (
21 |
122 | );
123 | }
124 |
--------------------------------------------------------------------------------
/app/ui/invoices/pagination.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
4 | import clsx from 'clsx';
5 | import Link from 'next/link';
6 | import { generatePagination } from '@/app/lib/utils';
7 |
8 | export default function Pagination({ totalPages }: { totalPages: number }) {
9 | // NOTE: Uncomment this code in Chapter 11
10 |
11 | // const allPages = generatePagination(currentPage, totalPages);
12 |
13 | return (
14 | <>
15 | {/* NOTE: Uncomment this code in Chapter 11 */}
16 |
17 | {/*
18 |
23 |
24 |
25 | {allPages.map((page, index) => {
26 | let position: 'first' | 'last' | 'single' | 'middle' | undefined;
27 |
28 | if (index === 0) position = 'first';
29 | if (index === allPages.length - 1) position = 'last';
30 | if (allPages.length === 1) position = 'single';
31 | if (page === '...') position = 'middle';
32 |
33 | return (
34 |
41 | );
42 | })}
43 |
44 |
45 |
= totalPages}
49 | />
50 | */}
51 | >
52 | );
53 | }
54 |
55 | function PaginationNumber({
56 | page,
57 | href,
58 | isActive,
59 | position,
60 | }: {
61 | page: number | string;
62 | href: string;
63 | position?: 'first' | 'last' | 'middle' | 'single';
64 | isActive: boolean;
65 | }) {
66 | const className = clsx(
67 | 'flex h-10 w-10 items-center justify-center text-sm border',
68 | {
69 | 'rounded-l-md': position === 'first' || position === 'single',
70 | 'rounded-r-md': position === 'last' || position === 'single',
71 | 'z-10 bg-blue-600 border-blue-600 text-white': isActive,
72 | 'hover:bg-gray-100': !isActive && position !== 'middle',
73 | 'text-gray-300': position === 'middle',
74 | },
75 | );
76 |
77 | return isActive || position === 'middle' ? (
78 | {page}
79 | ) : (
80 |
81 | {page}
82 |
83 | );
84 | }
85 |
86 | function PaginationArrow({
87 | href,
88 | direction,
89 | isDisabled,
90 | }: {
91 | href: string;
92 | direction: 'left' | 'right';
93 | isDisabled?: boolean;
94 | }) {
95 | const className = clsx(
96 | 'flex h-10 w-10 items-center justify-center rounded-md border',
97 | {
98 | 'pointer-events-none text-gray-300': isDisabled,
99 | 'hover:bg-gray-100': !isDisabled,
100 | 'mr-2 md:mr-4': direction === 'left',
101 | 'ml-2 md:ml-4': direction === 'right',
102 | },
103 | );
104 |
105 | const icon =
106 | direction === 'left' ? (
107 |
108 | ) : (
109 |
110 | );
111 |
112 | return isDisabled ? (
113 | {icon}
114 | ) : (
115 |
116 | {icon}
117 |
118 | );
119 | }
120 |
--------------------------------------------------------------------------------
/app/ui/invoices/status.tsx:
--------------------------------------------------------------------------------
1 | import { CheckIcon, ClockIcon } from '@heroicons/react/24/outline';
2 | import clsx from 'clsx';
3 |
4 | export default function InvoiceStatus({ status }: { status: string }) {
5 | return (
6 |
15 | {status === 'pending' ? (
16 | <>
17 | Pending
18 |
19 | >
20 | ) : null}
21 | {status === 'paid' ? (
22 | <>
23 | Paid
24 |
25 | >
26 | ) : null}
27 |
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/app/ui/invoices/table.tsx:
--------------------------------------------------------------------------------
1 | import Image from 'next/image';
2 | import { UpdateInvoice, DeleteInvoice } from '@/app/ui/invoices/buttons';
3 | import InvoiceStatus from '@/app/ui/invoices/status';
4 | import { formatDateToLocal, formatCurrency } from '@/app/lib/utils';
5 | import { fetchFilteredInvoices } from '@/app/lib/data';
6 |
7 | export default async function InvoicesTable({
8 | query,
9 | currentPage,
10 | }: {
11 | query: string;
12 | currentPage: number;
13 | }) {
14 | const invoices = await fetchFilteredInvoices(query, currentPage);
15 |
16 | return (
17 |
18 |
19 |
20 |
21 | {invoices?.map((invoice) => (
22 |
26 |
27 |
28 |
29 |
36 |
{invoice.name}
37 |
38 |
{invoice.email}
39 |
40 |
41 |
42 |
43 |
44 |
45 | {formatCurrency(invoice.amount)}
46 |
47 |
{formatDateToLocal(invoice.date)}
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | ))}
56 |
57 |
58 |
59 |
60 |
61 | Customer
62 | |
63 |
64 | Email
65 | |
66 |
67 | Amount
68 | |
69 |
70 | Date
71 | |
72 |
73 | Status
74 | |
75 |
76 | Edit
77 | |
78 |
79 |
80 |
81 | {invoices?.map((invoice) => (
82 |
86 |
87 |
88 |
95 | {invoice.name}
96 |
97 | |
98 |
99 | {invoice.email}
100 | |
101 |
102 | {formatCurrency(invoice.amount)}
103 | |
104 |
105 | {formatDateToLocal(invoice.date)}
106 | |
107 |
108 |
109 | |
110 |
111 |
112 |
113 |
114 |
115 | |
116 |
117 | ))}
118 |
119 |
120 |
121 |
122 |
123 | );
124 | }
125 |
--------------------------------------------------------------------------------
/app/ui/login-form.tsx:
--------------------------------------------------------------------------------
1 | import { lusitana } from '@/app/ui/fonts';
2 | import {
3 | AtSymbolIcon,
4 | KeyIcon,
5 | ExclamationCircleIcon,
6 | } from '@heroicons/react/24/outline';
7 | import { ArrowRightIcon } from '@heroicons/react/20/solid';
8 | import { Button } from './button';
9 |
10 | export default function LoginForm() {
11 | return (
12 |
66 | );
67 | }
68 |
--------------------------------------------------------------------------------
/app/ui/search.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
4 |
5 | export default function Search({ placeholder }: { placeholder: string }) {
6 | return (
7 |
8 |
11 |
15 |
16 |
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/app/ui/skeletons.tsx:
--------------------------------------------------------------------------------
1 | // Loading animation
2 | const shimmer =
3 | 'before:absolute before:inset-0 before:-translate-x-full before:animate-[shimmer_2s_infinite] before:bg-gradient-to-r before:from-transparent before:via-white/60 before:to-transparent';
4 |
5 | export function CardSkeleton() {
6 | return (
7 |
18 | );
19 | }
20 |
21 | export function CardsSkeleton() {
22 | return (
23 | <>
24 |
25 |
26 |
27 |
28 | >
29 | );
30 | }
31 |
32 | export function RevenueChartSkeleton() {
33 | return (
34 |
44 | );
45 | }
46 |
47 | export function InvoiceSkeleton() {
48 | return (
49 |
59 | );
60 | }
61 |
62 | export function LatestInvoicesSkeleton() {
63 | return (
64 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
80 |
81 |
82 | );
83 | }
84 |
85 | export default function DashboardSkeleton() {
86 | return (
87 | <>
88 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | >
102 | );
103 | }
104 |
105 | export function TableRowSkeleton() {
106 | return (
107 |
108 | {/* Customer Name and Image */}
109 |
110 |
114 | |
115 | {/* Email */}
116 |
117 |
118 | |
119 | {/* Amount */}
120 |
121 |
122 | |
123 | {/* Date */}
124 |
125 |
126 | |
127 | {/* Status */}
128 |
129 |
130 | |
131 | {/* Actions */}
132 |
133 |
137 | |
138 |
139 | );
140 | }
141 |
142 | export function InvoicesMobileSkeleton() {
143 | return (
144 |
163 | );
164 | }
165 |
166 | export function InvoicesTableSkeleton() {
167 | return (
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 | Customer
184 | |
185 |
186 | Email
187 | |
188 |
189 | Amount
190 | |
191 |
192 | Date
193 | |
194 |
195 | Status
196 | |
197 |
201 | Edit
202 | |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 | );
218 | }
219 |
--------------------------------------------------------------------------------
/next.config.ts:
--------------------------------------------------------------------------------
1 | import type { NextConfig } from 'next';
2 |
3 | const nextConfig: NextConfig = {
4 | /* config options here */
5 | };
6 |
7 | export default nextConfig;
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "build": "next build",
5 | "dev": "next dev --turbopack",
6 | "start": "next start"
7 | },
8 | "dependencies": {
9 | "@heroicons/react": "^2.2.0",
10 | "@tailwindcss/forms": "^0.5.10",
11 | "autoprefixer": "10.4.20",
12 | "bcrypt": "^5.1.1",
13 | "clsx": "^2.1.1",
14 | "next": "latest",
15 | "next-auth": "5.0.0-beta.25",
16 | "postcss": "8.5.1",
17 | "postgres": "^3.4.5",
18 | "react": "latest",
19 | "react-dom": "latest",
20 | "tailwindcss": "3.4.17",
21 | "typescript": "5.7.3",
22 | "use-debounce": "^10.0.4",
23 | "zod": "^3.24.1"
24 | },
25 | "devDependencies": {
26 | "@types/bcrypt": "^5.0.2",
27 | "@types/node": "22.10.7",
28 | "@types/react": "19.0.7",
29 | "@types/react-dom": "19.0.3"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | importers:
8 |
9 | .:
10 | dependencies:
11 | '@heroicons/react':
12 | specifier: ^2.2.0
13 | version: 2.2.0(react@19.0.0)
14 | '@tailwindcss/forms':
15 | specifier: ^0.5.10
16 | version: 0.5.10(tailwindcss@3.4.17)
17 | autoprefixer:
18 | specifier: 10.4.20
19 | version: 10.4.20(postcss@8.5.1)
20 | bcrypt:
21 | specifier: ^5.1.1
22 | version: 5.1.1
23 | clsx:
24 | specifier: ^2.1.1
25 | version: 2.1.1
26 | next:
27 | specifier: latest
28 | version: 15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
29 | next-auth:
30 | specifier: 5.0.0-beta.25
31 | version: 5.0.0-beta.25(next@15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)
32 | postcss:
33 | specifier: 8.5.1
34 | version: 8.5.1
35 | postgres:
36 | specifier: ^3.4.5
37 | version: 3.4.5
38 | react:
39 | specifier: latest
40 | version: 19.0.0
41 | react-dom:
42 | specifier: latest
43 | version: 19.0.0(react@19.0.0)
44 | tailwindcss:
45 | specifier: 3.4.17
46 | version: 3.4.17
47 | typescript:
48 | specifier: 5.7.3
49 | version: 5.7.3
50 | use-debounce:
51 | specifier: ^10.0.4
52 | version: 10.0.4(react@19.0.0)
53 | zod:
54 | specifier: ^3.24.1
55 | version: 3.24.1
56 | devDependencies:
57 | '@types/bcrypt':
58 | specifier: ^5.0.2
59 | version: 5.0.2
60 | '@types/node':
61 | specifier: 22.10.7
62 | version: 22.10.7
63 | '@types/react':
64 | specifier: 19.0.7
65 | version: 19.0.7
66 | '@types/react-dom':
67 | specifier: 19.0.3
68 | version: 19.0.3(@types/react@19.0.7)
69 |
70 | packages:
71 |
72 | '@alloc/quick-lru@5.2.0':
73 | resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
74 | engines: {node: '>=10'}
75 |
76 | '@auth/core@0.37.2':
77 | resolution: {integrity: sha512-kUvzyvkcd6h1vpeMAojK2y7+PAV5H+0Cc9+ZlKYDFhDY31AlvsB+GW5vNO4qE3Y07KeQgvNO9U0QUx/fN62kBw==}
78 | peerDependencies:
79 | '@simplewebauthn/browser': ^9.0.1
80 | '@simplewebauthn/server': ^9.0.2
81 | nodemailer: ^6.8.0
82 | peerDependenciesMeta:
83 | '@simplewebauthn/browser':
84 | optional: true
85 | '@simplewebauthn/server':
86 | optional: true
87 | nodemailer:
88 | optional: true
89 |
90 | '@emnapi/runtime@1.3.1':
91 | resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==}
92 |
93 | '@heroicons/react@2.2.0':
94 | resolution: {integrity: sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==}
95 | peerDependencies:
96 | react: '>= 16 || ^19.0.0-rc'
97 |
98 | '@img/sharp-darwin-arm64@0.33.5':
99 | resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==}
100 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
101 | cpu: [arm64]
102 | os: [darwin]
103 |
104 | '@img/sharp-darwin-x64@0.33.5':
105 | resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==}
106 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
107 | cpu: [x64]
108 | os: [darwin]
109 |
110 | '@img/sharp-libvips-darwin-arm64@1.0.4':
111 | resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==}
112 | cpu: [arm64]
113 | os: [darwin]
114 |
115 | '@img/sharp-libvips-darwin-x64@1.0.4':
116 | resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==}
117 | cpu: [x64]
118 | os: [darwin]
119 |
120 | '@img/sharp-libvips-linux-arm64@1.0.4':
121 | resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
122 | cpu: [arm64]
123 | os: [linux]
124 |
125 | '@img/sharp-libvips-linux-arm@1.0.5':
126 | resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
127 | cpu: [arm]
128 | os: [linux]
129 |
130 | '@img/sharp-libvips-linux-s390x@1.0.4':
131 | resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
132 | cpu: [s390x]
133 | os: [linux]
134 |
135 | '@img/sharp-libvips-linux-x64@1.0.4':
136 | resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
137 | cpu: [x64]
138 | os: [linux]
139 |
140 | '@img/sharp-libvips-linuxmusl-arm64@1.0.4':
141 | resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
142 | cpu: [arm64]
143 | os: [linux]
144 |
145 | '@img/sharp-libvips-linuxmusl-x64@1.0.4':
146 | resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
147 | cpu: [x64]
148 | os: [linux]
149 |
150 | '@img/sharp-linux-arm64@0.33.5':
151 | resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
152 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
153 | cpu: [arm64]
154 | os: [linux]
155 |
156 | '@img/sharp-linux-arm@0.33.5':
157 | resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
158 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
159 | cpu: [arm]
160 | os: [linux]
161 |
162 | '@img/sharp-linux-s390x@0.33.5':
163 | resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
164 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
165 | cpu: [s390x]
166 | os: [linux]
167 |
168 | '@img/sharp-linux-x64@0.33.5':
169 | resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
170 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
171 | cpu: [x64]
172 | os: [linux]
173 |
174 | '@img/sharp-linuxmusl-arm64@0.33.5':
175 | resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
176 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
177 | cpu: [arm64]
178 | os: [linux]
179 |
180 | '@img/sharp-linuxmusl-x64@0.33.5':
181 | resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
182 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
183 | cpu: [x64]
184 | os: [linux]
185 |
186 | '@img/sharp-wasm32@0.33.5':
187 | resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
188 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
189 | cpu: [wasm32]
190 |
191 | '@img/sharp-win32-ia32@0.33.5':
192 | resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==}
193 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
194 | cpu: [ia32]
195 | os: [win32]
196 |
197 | '@img/sharp-win32-x64@0.33.5':
198 | resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==}
199 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
200 | cpu: [x64]
201 | os: [win32]
202 |
203 | '@isaacs/cliui@8.0.2':
204 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
205 | engines: {node: '>=12'}
206 |
207 | '@jridgewell/gen-mapping@0.3.8':
208 | resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
209 | engines: {node: '>=6.0.0'}
210 |
211 | '@jridgewell/resolve-uri@3.1.2':
212 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
213 | engines: {node: '>=6.0.0'}
214 |
215 | '@jridgewell/set-array@1.2.1':
216 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
217 | engines: {node: '>=6.0.0'}
218 |
219 | '@jridgewell/sourcemap-codec@1.5.0':
220 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
221 |
222 | '@jridgewell/trace-mapping@0.3.25':
223 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
224 |
225 | '@mapbox/node-pre-gyp@1.0.11':
226 | resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
227 | hasBin: true
228 |
229 | '@next/env@15.1.6':
230 | resolution: {integrity: sha512-d9AFQVPEYNr+aqokIiPLNK/MTyt3DWa/dpKveiAaVccUadFbhFEvY6FXYX2LJO2Hv7PHnLBu2oWwB4uBuHjr/w==}
231 |
232 | '@next/swc-darwin-arm64@15.1.6':
233 | resolution: {integrity: sha512-u7lg4Mpl9qWpKgy6NzEkz/w0/keEHtOybmIl0ykgItBxEM5mYotS5PmqTpo+Rhg8FiOiWgwr8USxmKQkqLBCrw==}
234 | engines: {node: '>= 10'}
235 | cpu: [arm64]
236 | os: [darwin]
237 |
238 | '@next/swc-darwin-x64@15.1.6':
239 | resolution: {integrity: sha512-x1jGpbHbZoZ69nRuogGL2MYPLqohlhnT9OCU6E6QFewwup+z+M6r8oU47BTeJcWsF2sdBahp5cKiAcDbwwK/lg==}
240 | engines: {node: '>= 10'}
241 | cpu: [x64]
242 | os: [darwin]
243 |
244 | '@next/swc-linux-arm64-gnu@15.1.6':
245 | resolution: {integrity: sha512-jar9sFw0XewXsBzPf9runGzoivajeWJUc/JkfbLTC4it9EhU8v7tCRLH7l5Y1ReTMN6zKJO0kKAGqDk8YSO2bg==}
246 | engines: {node: '>= 10'}
247 | cpu: [arm64]
248 | os: [linux]
249 |
250 | '@next/swc-linux-arm64-musl@15.1.6':
251 | resolution: {integrity: sha512-+n3u//bfsrIaZch4cgOJ3tXCTbSxz0s6brJtU3SzLOvkJlPQMJ+eHVRi6qM2kKKKLuMY+tcau8XD9CJ1OjeSQQ==}
252 | engines: {node: '>= 10'}
253 | cpu: [arm64]
254 | os: [linux]
255 |
256 | '@next/swc-linux-x64-gnu@15.1.6':
257 | resolution: {integrity: sha512-SpuDEXixM3PycniL4iVCLyUyvcl6Lt0mtv3am08sucskpG0tYkW1KlRhTgj4LI5ehyxriVVcfdoxuuP8csi3kQ==}
258 | engines: {node: '>= 10'}
259 | cpu: [x64]
260 | os: [linux]
261 |
262 | '@next/swc-linux-x64-musl@15.1.6':
263 | resolution: {integrity: sha512-L4druWmdFSZIIRhF+G60API5sFB7suTbDRhYWSjiw0RbE+15igQvE2g2+S973pMGvwN3guw7cJUjA/TmbPWTHQ==}
264 | engines: {node: '>= 10'}
265 | cpu: [x64]
266 | os: [linux]
267 |
268 | '@next/swc-win32-arm64-msvc@15.1.6':
269 | resolution: {integrity: sha512-s8w6EeqNmi6gdvM19tqKKWbCyOBvXFbndkGHl+c9YrzsLARRdCHsD9S1fMj8gsXm9v8vhC8s3N8rjuC/XrtkEg==}
270 | engines: {node: '>= 10'}
271 | cpu: [arm64]
272 | os: [win32]
273 |
274 | '@next/swc-win32-x64-msvc@15.1.6':
275 | resolution: {integrity: sha512-6xomMuu54FAFxttYr5PJbEfu96godcxBTRk1OhAvJq0/EnmFU/Ybiax30Snis4vdWZ9LGpf7Roy5fSs7v/5ROQ==}
276 | engines: {node: '>= 10'}
277 | cpu: [x64]
278 | os: [win32]
279 |
280 | '@nodelib/fs.scandir@2.1.5':
281 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
282 | engines: {node: '>= 8'}
283 |
284 | '@nodelib/fs.stat@2.0.5':
285 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
286 | engines: {node: '>= 8'}
287 |
288 | '@nodelib/fs.walk@1.2.8':
289 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
290 | engines: {node: '>= 8'}
291 |
292 | '@panva/hkdf@1.2.1':
293 | resolution: {integrity: sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==}
294 |
295 | '@pkgjs/parseargs@0.11.0':
296 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
297 | engines: {node: '>=14'}
298 |
299 | '@swc/counter@0.1.3':
300 | resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
301 |
302 | '@swc/helpers@0.5.15':
303 | resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
304 |
305 | '@tailwindcss/forms@0.5.10':
306 | resolution: {integrity: sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==}
307 | peerDependencies:
308 | tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1'
309 |
310 | '@types/bcrypt@5.0.2':
311 | resolution: {integrity: sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==}
312 |
313 | '@types/cookie@0.6.0':
314 | resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
315 |
316 | '@types/node@22.10.7':
317 | resolution: {integrity: sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==}
318 |
319 | '@types/react-dom@19.0.3':
320 | resolution: {integrity: sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==}
321 | peerDependencies:
322 | '@types/react': ^19.0.0
323 |
324 | '@types/react@19.0.7':
325 | resolution: {integrity: sha512-MoFsEJKkAtZCrC1r6CM8U22GzhG7u2Wir8ons/aCKH6MBdD1ibV24zOSSkdZVUKqN5i396zG5VKLYZ3yaUZdLA==}
326 |
327 | abbrev@1.1.1:
328 | resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
329 |
330 | agent-base@6.0.2:
331 | resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
332 | engines: {node: '>= 6.0.0'}
333 |
334 | ansi-regex@5.0.1:
335 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
336 | engines: {node: '>=8'}
337 |
338 | ansi-regex@6.1.0:
339 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
340 | engines: {node: '>=12'}
341 |
342 | ansi-styles@4.3.0:
343 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
344 | engines: {node: '>=8'}
345 |
346 | ansi-styles@6.2.1:
347 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
348 | engines: {node: '>=12'}
349 |
350 | any-promise@1.3.0:
351 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
352 |
353 | anymatch@3.1.3:
354 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
355 | engines: {node: '>= 8'}
356 |
357 | aproba@2.0.0:
358 | resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
359 |
360 | are-we-there-yet@2.0.0:
361 | resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
362 | engines: {node: '>=10'}
363 | deprecated: This package is no longer supported.
364 |
365 | arg@5.0.2:
366 | resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
367 |
368 | autoprefixer@10.4.20:
369 | resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==}
370 | engines: {node: ^10 || ^12 || >=14}
371 | hasBin: true
372 | peerDependencies:
373 | postcss: ^8.1.0
374 |
375 | balanced-match@1.0.2:
376 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
377 |
378 | bcrypt@5.1.1:
379 | resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==}
380 | engines: {node: '>= 10.0.0'}
381 |
382 | binary-extensions@2.3.0:
383 | resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
384 | engines: {node: '>=8'}
385 |
386 | brace-expansion@1.1.11:
387 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
388 |
389 | brace-expansion@2.0.1:
390 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
391 |
392 | braces@3.0.3:
393 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
394 | engines: {node: '>=8'}
395 |
396 | browserslist@4.24.4:
397 | resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==}
398 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
399 | hasBin: true
400 |
401 | busboy@1.6.0:
402 | resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
403 | engines: {node: '>=10.16.0'}
404 |
405 | camelcase-css@2.0.1:
406 | resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
407 | engines: {node: '>= 6'}
408 |
409 | caniuse-lite@1.0.30001695:
410 | resolution: {integrity: sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==}
411 |
412 | chokidar@3.6.0:
413 | resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
414 | engines: {node: '>= 8.10.0'}
415 |
416 | chownr@2.0.0:
417 | resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
418 | engines: {node: '>=10'}
419 |
420 | client-only@0.0.1:
421 | resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
422 |
423 | clsx@2.1.1:
424 | resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
425 | engines: {node: '>=6'}
426 |
427 | color-convert@2.0.1:
428 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
429 | engines: {node: '>=7.0.0'}
430 |
431 | color-name@1.1.4:
432 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
433 |
434 | color-string@1.9.1:
435 | resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
436 |
437 | color-support@1.1.3:
438 | resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
439 | hasBin: true
440 |
441 | color@4.2.3:
442 | resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
443 | engines: {node: '>=12.5.0'}
444 |
445 | commander@4.1.1:
446 | resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
447 | engines: {node: '>= 6'}
448 |
449 | concat-map@0.0.1:
450 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
451 |
452 | console-control-strings@1.1.0:
453 | resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
454 |
455 | cookie@0.7.1:
456 | resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==}
457 | engines: {node: '>= 0.6'}
458 |
459 | cross-spawn@7.0.6:
460 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
461 | engines: {node: '>= 8'}
462 |
463 | cssesc@3.0.0:
464 | resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
465 | engines: {node: '>=4'}
466 | hasBin: true
467 |
468 | csstype@3.1.3:
469 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
470 |
471 | debug@4.4.0:
472 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
473 | engines: {node: '>=6.0'}
474 | peerDependencies:
475 | supports-color: '*'
476 | peerDependenciesMeta:
477 | supports-color:
478 | optional: true
479 |
480 | delegates@1.0.0:
481 | resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
482 |
483 | detect-libc@2.0.3:
484 | resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
485 | engines: {node: '>=8'}
486 |
487 | didyoumean@1.2.2:
488 | resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
489 |
490 | dlv@1.1.3:
491 | resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
492 |
493 | eastasianwidth@0.2.0:
494 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
495 |
496 | electron-to-chromium@1.5.83:
497 | resolution: {integrity: sha512-LcUDPqSt+V0QmI47XLzZrz5OqILSMGsPFkDYus22rIbgorSvBYEFqq854ltTmUdHkY92FSdAAvsh4jWEULMdfQ==}
498 |
499 | emoji-regex@8.0.0:
500 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
501 |
502 | emoji-regex@9.2.2:
503 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
504 |
505 | escalade@3.2.0:
506 | resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
507 | engines: {node: '>=6'}
508 |
509 | fast-glob@3.3.3:
510 | resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
511 | engines: {node: '>=8.6.0'}
512 |
513 | fastq@1.18.0:
514 | resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==}
515 |
516 | fill-range@7.1.1:
517 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
518 | engines: {node: '>=8'}
519 |
520 | foreground-child@3.3.0:
521 | resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
522 | engines: {node: '>=14'}
523 |
524 | fraction.js@4.3.7:
525 | resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
526 |
527 | fs-minipass@2.1.0:
528 | resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
529 | engines: {node: '>= 8'}
530 |
531 | fs.realpath@1.0.0:
532 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
533 |
534 | fsevents@2.3.3:
535 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
536 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
537 | os: [darwin]
538 |
539 | function-bind@1.1.2:
540 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
541 |
542 | gauge@3.0.2:
543 | resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
544 | engines: {node: '>=10'}
545 | deprecated: This package is no longer supported.
546 |
547 | glob-parent@5.1.2:
548 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
549 | engines: {node: '>= 6'}
550 |
551 | glob-parent@6.0.2:
552 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
553 | engines: {node: '>=10.13.0'}
554 |
555 | glob@10.4.5:
556 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
557 | hasBin: true
558 |
559 | glob@7.2.3:
560 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
561 | deprecated: Glob versions prior to v9 are no longer supported
562 |
563 | has-unicode@2.0.1:
564 | resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
565 |
566 | hasown@2.0.2:
567 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
568 | engines: {node: '>= 0.4'}
569 |
570 | https-proxy-agent@5.0.1:
571 | resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
572 | engines: {node: '>= 6'}
573 |
574 | inflight@1.0.6:
575 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
576 | deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
577 |
578 | inherits@2.0.4:
579 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
580 |
581 | is-arrayish@0.3.2:
582 | resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
583 |
584 | is-binary-path@2.1.0:
585 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
586 | engines: {node: '>=8'}
587 |
588 | is-core-module@2.16.1:
589 | resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
590 | engines: {node: '>= 0.4'}
591 |
592 | is-extglob@2.1.1:
593 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
594 | engines: {node: '>=0.10.0'}
595 |
596 | is-fullwidth-code-point@3.0.0:
597 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
598 | engines: {node: '>=8'}
599 |
600 | is-glob@4.0.3:
601 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
602 | engines: {node: '>=0.10.0'}
603 |
604 | is-number@7.0.0:
605 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
606 | engines: {node: '>=0.12.0'}
607 |
608 | isexe@2.0.0:
609 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
610 |
611 | jackspeak@3.4.3:
612 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
613 |
614 | jiti@1.21.7:
615 | resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
616 | hasBin: true
617 |
618 | jose@5.9.6:
619 | resolution: {integrity: sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==}
620 |
621 | lilconfig@3.1.3:
622 | resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
623 | engines: {node: '>=14'}
624 |
625 | lines-and-columns@1.2.4:
626 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
627 |
628 | lru-cache@10.4.3:
629 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
630 |
631 | make-dir@3.1.0:
632 | resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
633 | engines: {node: '>=8'}
634 |
635 | merge2@1.4.1:
636 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
637 | engines: {node: '>= 8'}
638 |
639 | micromatch@4.0.8:
640 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
641 | engines: {node: '>=8.6'}
642 |
643 | mini-svg-data-uri@1.4.4:
644 | resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==}
645 | hasBin: true
646 |
647 | minimatch@3.1.2:
648 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
649 |
650 | minimatch@9.0.5:
651 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
652 | engines: {node: '>=16 || 14 >=14.17'}
653 |
654 | minipass@3.3.6:
655 | resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
656 | engines: {node: '>=8'}
657 |
658 | minipass@5.0.0:
659 | resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
660 | engines: {node: '>=8'}
661 |
662 | minipass@7.1.2:
663 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
664 | engines: {node: '>=16 || 14 >=14.17'}
665 |
666 | minizlib@2.1.2:
667 | resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
668 | engines: {node: '>= 8'}
669 |
670 | mkdirp@1.0.4:
671 | resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
672 | engines: {node: '>=10'}
673 | hasBin: true
674 |
675 | ms@2.1.3:
676 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
677 |
678 | mz@2.7.0:
679 | resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
680 |
681 | nanoid@3.3.8:
682 | resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
683 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
684 | hasBin: true
685 |
686 | next-auth@5.0.0-beta.25:
687 | resolution: {integrity: sha512-2dJJw1sHQl2qxCrRk+KTQbeH+izFbGFPuJj5eGgBZFYyiYYtvlrBeUw1E/OJJxTRjuxbSYGnCTkUIRsIIW0bog==}
688 | peerDependencies:
689 | '@simplewebauthn/browser': ^9.0.1
690 | '@simplewebauthn/server': ^9.0.2
691 | next: ^14.0.0-0 || ^15.0.0-0
692 | nodemailer: ^6.6.5
693 | react: ^18.2.0 || ^19.0.0-0
694 | peerDependenciesMeta:
695 | '@simplewebauthn/browser':
696 | optional: true
697 | '@simplewebauthn/server':
698 | optional: true
699 | nodemailer:
700 | optional: true
701 |
702 | next@15.1.6:
703 | resolution: {integrity: sha512-Hch4wzbaX0vKQtalpXvUiw5sYivBy4cm5rzUKrBnUB/y436LGrvOUqYvlSeNVCWFO/770gDlltR9gqZH62ct4Q==}
704 | engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
705 | hasBin: true
706 | peerDependencies:
707 | '@opentelemetry/api': ^1.1.0
708 | '@playwright/test': ^1.41.2
709 | babel-plugin-react-compiler: '*'
710 | react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
711 | react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
712 | sass: ^1.3.0
713 | peerDependenciesMeta:
714 | '@opentelemetry/api':
715 | optional: true
716 | '@playwright/test':
717 | optional: true
718 | babel-plugin-react-compiler:
719 | optional: true
720 | sass:
721 | optional: true
722 |
723 | node-addon-api@5.1.0:
724 | resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==}
725 |
726 | node-fetch@2.7.0:
727 | resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
728 | engines: {node: 4.x || >=6.0.0}
729 | peerDependencies:
730 | encoding: ^0.1.0
731 | peerDependenciesMeta:
732 | encoding:
733 | optional: true
734 |
735 | node-releases@2.0.19:
736 | resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
737 |
738 | nopt@5.0.0:
739 | resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
740 | engines: {node: '>=6'}
741 | hasBin: true
742 |
743 | normalize-path@3.0.0:
744 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
745 | engines: {node: '>=0.10.0'}
746 |
747 | normalize-range@0.1.2:
748 | resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
749 | engines: {node: '>=0.10.0'}
750 |
751 | npmlog@5.0.1:
752 | resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
753 | deprecated: This package is no longer supported.
754 |
755 | oauth4webapi@3.1.4:
756 | resolution: {integrity: sha512-eVfN3nZNbok2s/ROifO0UAc5G8nRoLSbrcKJ09OqmucgnhXEfdIQOR4gq1eJH1rN3gV7rNw62bDEgftsgFtBEg==}
757 |
758 | object-assign@4.1.1:
759 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
760 | engines: {node: '>=0.10.0'}
761 |
762 | object-hash@3.0.0:
763 | resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
764 | engines: {node: '>= 6'}
765 |
766 | once@1.4.0:
767 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
768 |
769 | package-json-from-dist@1.0.1:
770 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
771 |
772 | path-is-absolute@1.0.1:
773 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
774 | engines: {node: '>=0.10.0'}
775 |
776 | path-key@3.1.1:
777 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
778 | engines: {node: '>=8'}
779 |
780 | path-parse@1.0.7:
781 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
782 |
783 | path-scurry@1.11.1:
784 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
785 | engines: {node: '>=16 || 14 >=14.18'}
786 |
787 | picocolors@1.1.1:
788 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
789 |
790 | picomatch@2.3.1:
791 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
792 | engines: {node: '>=8.6'}
793 |
794 | pify@2.3.0:
795 | resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
796 | engines: {node: '>=0.10.0'}
797 |
798 | pirates@4.0.6:
799 | resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
800 | engines: {node: '>= 6'}
801 |
802 | postcss-import@15.1.0:
803 | resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
804 | engines: {node: '>=14.0.0'}
805 | peerDependencies:
806 | postcss: ^8.0.0
807 |
808 | postcss-js@4.0.1:
809 | resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
810 | engines: {node: ^12 || ^14 || >= 16}
811 | peerDependencies:
812 | postcss: ^8.4.21
813 |
814 | postcss-load-config@4.0.2:
815 | resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
816 | engines: {node: '>= 14'}
817 | peerDependencies:
818 | postcss: '>=8.0.9'
819 | ts-node: '>=9.0.0'
820 | peerDependenciesMeta:
821 | postcss:
822 | optional: true
823 | ts-node:
824 | optional: true
825 |
826 | postcss-nested@6.2.0:
827 | resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
828 | engines: {node: '>=12.0'}
829 | peerDependencies:
830 | postcss: ^8.2.14
831 |
832 | postcss-selector-parser@6.1.2:
833 | resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
834 | engines: {node: '>=4'}
835 |
836 | postcss-value-parser@4.2.0:
837 | resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
838 |
839 | postcss@8.4.31:
840 | resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
841 | engines: {node: ^10 || ^12 || >=14}
842 |
843 | postcss@8.5.1:
844 | resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==}
845 | engines: {node: ^10 || ^12 || >=14}
846 |
847 | postgres@3.4.5:
848 | resolution: {integrity: sha512-cDWgoah1Gez9rN3H4165peY9qfpEo+SA61oQv65O3cRUE1pOEoJWwddwcqKE8XZYjbblOJlYDlLV4h67HrEVDg==}
849 | engines: {node: '>=12'}
850 |
851 | preact-render-to-string@5.2.3:
852 | resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==}
853 | peerDependencies:
854 | preact: '>=10'
855 |
856 | preact@10.11.3:
857 | resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==}
858 |
859 | pretty-format@3.8.0:
860 | resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==}
861 |
862 | queue-microtask@1.2.3:
863 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
864 |
865 | react-dom@19.0.0:
866 | resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==}
867 | peerDependencies:
868 | react: ^19.0.0
869 |
870 | react@19.0.0:
871 | resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
872 | engines: {node: '>=0.10.0'}
873 |
874 | read-cache@1.0.0:
875 | resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
876 |
877 | readable-stream@3.6.2:
878 | resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
879 | engines: {node: '>= 6'}
880 |
881 | readdirp@3.6.0:
882 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
883 | engines: {node: '>=8.10.0'}
884 |
885 | resolve@1.22.10:
886 | resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
887 | engines: {node: '>= 0.4'}
888 | hasBin: true
889 |
890 | reusify@1.0.4:
891 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
892 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
893 |
894 | rimraf@3.0.2:
895 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
896 | deprecated: Rimraf versions prior to v4 are no longer supported
897 | hasBin: true
898 |
899 | run-parallel@1.2.0:
900 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
901 |
902 | safe-buffer@5.2.1:
903 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
904 |
905 | scheduler@0.25.0:
906 | resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==}
907 |
908 | semver@6.3.1:
909 | resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
910 | hasBin: true
911 |
912 | semver@7.6.3:
913 | resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
914 | engines: {node: '>=10'}
915 | hasBin: true
916 |
917 | set-blocking@2.0.0:
918 | resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
919 |
920 | sharp@0.33.5:
921 | resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==}
922 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
923 |
924 | shebang-command@2.0.0:
925 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
926 | engines: {node: '>=8'}
927 |
928 | shebang-regex@3.0.0:
929 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
930 | engines: {node: '>=8'}
931 |
932 | signal-exit@3.0.7:
933 | resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
934 |
935 | signal-exit@4.1.0:
936 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
937 | engines: {node: '>=14'}
938 |
939 | simple-swizzle@0.2.2:
940 | resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
941 |
942 | source-map-js@1.2.1:
943 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
944 | engines: {node: '>=0.10.0'}
945 |
946 | streamsearch@1.1.0:
947 | resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
948 | engines: {node: '>=10.0.0'}
949 |
950 | string-width@4.2.3:
951 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
952 | engines: {node: '>=8'}
953 |
954 | string-width@5.1.2:
955 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
956 | engines: {node: '>=12'}
957 |
958 | string_decoder@1.3.0:
959 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
960 |
961 | strip-ansi@6.0.1:
962 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
963 | engines: {node: '>=8'}
964 |
965 | strip-ansi@7.1.0:
966 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
967 | engines: {node: '>=12'}
968 |
969 | styled-jsx@5.1.6:
970 | resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
971 | engines: {node: '>= 12.0.0'}
972 | peerDependencies:
973 | '@babel/core': '*'
974 | babel-plugin-macros: '*'
975 | react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0'
976 | peerDependenciesMeta:
977 | '@babel/core':
978 | optional: true
979 | babel-plugin-macros:
980 | optional: true
981 |
982 | sucrase@3.35.0:
983 | resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
984 | engines: {node: '>=16 || 14 >=14.17'}
985 | hasBin: true
986 |
987 | supports-preserve-symlinks-flag@1.0.0:
988 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
989 | engines: {node: '>= 0.4'}
990 |
991 | tailwindcss@3.4.17:
992 | resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
993 | engines: {node: '>=14.0.0'}
994 | hasBin: true
995 |
996 | tar@6.2.1:
997 | resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
998 | engines: {node: '>=10'}
999 |
1000 | thenify-all@1.6.0:
1001 | resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
1002 | engines: {node: '>=0.8'}
1003 |
1004 | thenify@3.3.1:
1005 | resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
1006 |
1007 | to-regex-range@5.0.1:
1008 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
1009 | engines: {node: '>=8.0'}
1010 |
1011 | tr46@0.0.3:
1012 | resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
1013 |
1014 | ts-interface-checker@0.1.13:
1015 | resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
1016 |
1017 | tslib@2.8.1:
1018 | resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
1019 |
1020 | typescript@5.7.3:
1021 | resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==}
1022 | engines: {node: '>=14.17'}
1023 | hasBin: true
1024 |
1025 | undici-types@6.20.0:
1026 | resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
1027 |
1028 | update-browserslist-db@1.1.2:
1029 | resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==}
1030 | hasBin: true
1031 | peerDependencies:
1032 | browserslist: '>= 4.21.0'
1033 |
1034 | use-debounce@10.0.4:
1035 | resolution: {integrity: sha512-6Cf7Yr7Wk7Kdv77nnJMf6de4HuDE4dTxKij+RqE9rufDsI6zsbjyAxcH5y2ueJCQAnfgKbzXbZHYlkFwmBlWkw==}
1036 | engines: {node: '>= 16.0.0'}
1037 | peerDependencies:
1038 | react: '*'
1039 |
1040 | util-deprecate@1.0.2:
1041 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
1042 |
1043 | webidl-conversions@3.0.1:
1044 | resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
1045 |
1046 | whatwg-url@5.0.0:
1047 | resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
1048 |
1049 | which@2.0.2:
1050 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
1051 | engines: {node: '>= 8'}
1052 | hasBin: true
1053 |
1054 | wide-align@1.1.5:
1055 | resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
1056 |
1057 | wrap-ansi@7.0.0:
1058 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
1059 | engines: {node: '>=10'}
1060 |
1061 | wrap-ansi@8.1.0:
1062 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
1063 | engines: {node: '>=12'}
1064 |
1065 | wrappy@1.0.2:
1066 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
1067 |
1068 | yallist@4.0.0:
1069 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
1070 |
1071 | yaml@2.7.0:
1072 | resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==}
1073 | engines: {node: '>= 14'}
1074 | hasBin: true
1075 |
1076 | zod@3.24.1:
1077 | resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==}
1078 |
1079 | snapshots:
1080 |
1081 | '@alloc/quick-lru@5.2.0': {}
1082 |
1083 | '@auth/core@0.37.2':
1084 | dependencies:
1085 | '@panva/hkdf': 1.2.1
1086 | '@types/cookie': 0.6.0
1087 | cookie: 0.7.1
1088 | jose: 5.9.6
1089 | oauth4webapi: 3.1.4
1090 | preact: 10.11.3
1091 | preact-render-to-string: 5.2.3(preact@10.11.3)
1092 |
1093 | '@emnapi/runtime@1.3.1':
1094 | dependencies:
1095 | tslib: 2.8.1
1096 | optional: true
1097 |
1098 | '@heroicons/react@2.2.0(react@19.0.0)':
1099 | dependencies:
1100 | react: 19.0.0
1101 |
1102 | '@img/sharp-darwin-arm64@0.33.5':
1103 | optionalDependencies:
1104 | '@img/sharp-libvips-darwin-arm64': 1.0.4
1105 | optional: true
1106 |
1107 | '@img/sharp-darwin-x64@0.33.5':
1108 | optionalDependencies:
1109 | '@img/sharp-libvips-darwin-x64': 1.0.4
1110 | optional: true
1111 |
1112 | '@img/sharp-libvips-darwin-arm64@1.0.4':
1113 | optional: true
1114 |
1115 | '@img/sharp-libvips-darwin-x64@1.0.4':
1116 | optional: true
1117 |
1118 | '@img/sharp-libvips-linux-arm64@1.0.4':
1119 | optional: true
1120 |
1121 | '@img/sharp-libvips-linux-arm@1.0.5':
1122 | optional: true
1123 |
1124 | '@img/sharp-libvips-linux-s390x@1.0.4':
1125 | optional: true
1126 |
1127 | '@img/sharp-libvips-linux-x64@1.0.4':
1128 | optional: true
1129 |
1130 | '@img/sharp-libvips-linuxmusl-arm64@1.0.4':
1131 | optional: true
1132 |
1133 | '@img/sharp-libvips-linuxmusl-x64@1.0.4':
1134 | optional: true
1135 |
1136 | '@img/sharp-linux-arm64@0.33.5':
1137 | optionalDependencies:
1138 | '@img/sharp-libvips-linux-arm64': 1.0.4
1139 | optional: true
1140 |
1141 | '@img/sharp-linux-arm@0.33.5':
1142 | optionalDependencies:
1143 | '@img/sharp-libvips-linux-arm': 1.0.5
1144 | optional: true
1145 |
1146 | '@img/sharp-linux-s390x@0.33.5':
1147 | optionalDependencies:
1148 | '@img/sharp-libvips-linux-s390x': 1.0.4
1149 | optional: true
1150 |
1151 | '@img/sharp-linux-x64@0.33.5':
1152 | optionalDependencies:
1153 | '@img/sharp-libvips-linux-x64': 1.0.4
1154 | optional: true
1155 |
1156 | '@img/sharp-linuxmusl-arm64@0.33.5':
1157 | optionalDependencies:
1158 | '@img/sharp-libvips-linuxmusl-arm64': 1.0.4
1159 | optional: true
1160 |
1161 | '@img/sharp-linuxmusl-x64@0.33.5':
1162 | optionalDependencies:
1163 | '@img/sharp-libvips-linuxmusl-x64': 1.0.4
1164 | optional: true
1165 |
1166 | '@img/sharp-wasm32@0.33.5':
1167 | dependencies:
1168 | '@emnapi/runtime': 1.3.1
1169 | optional: true
1170 |
1171 | '@img/sharp-win32-ia32@0.33.5':
1172 | optional: true
1173 |
1174 | '@img/sharp-win32-x64@0.33.5':
1175 | optional: true
1176 |
1177 | '@isaacs/cliui@8.0.2':
1178 | dependencies:
1179 | string-width: 5.1.2
1180 | string-width-cjs: string-width@4.2.3
1181 | strip-ansi: 7.1.0
1182 | strip-ansi-cjs: strip-ansi@6.0.1
1183 | wrap-ansi: 8.1.0
1184 | wrap-ansi-cjs: wrap-ansi@7.0.0
1185 |
1186 | '@jridgewell/gen-mapping@0.3.8':
1187 | dependencies:
1188 | '@jridgewell/set-array': 1.2.1
1189 | '@jridgewell/sourcemap-codec': 1.5.0
1190 | '@jridgewell/trace-mapping': 0.3.25
1191 |
1192 | '@jridgewell/resolve-uri@3.1.2': {}
1193 |
1194 | '@jridgewell/set-array@1.2.1': {}
1195 |
1196 | '@jridgewell/sourcemap-codec@1.5.0': {}
1197 |
1198 | '@jridgewell/trace-mapping@0.3.25':
1199 | dependencies:
1200 | '@jridgewell/resolve-uri': 3.1.2
1201 | '@jridgewell/sourcemap-codec': 1.5.0
1202 |
1203 | '@mapbox/node-pre-gyp@1.0.11':
1204 | dependencies:
1205 | detect-libc: 2.0.3
1206 | https-proxy-agent: 5.0.1
1207 | make-dir: 3.1.0
1208 | node-fetch: 2.7.0
1209 | nopt: 5.0.0
1210 | npmlog: 5.0.1
1211 | rimraf: 3.0.2
1212 | semver: 7.6.3
1213 | tar: 6.2.1
1214 | transitivePeerDependencies:
1215 | - encoding
1216 | - supports-color
1217 |
1218 | '@next/env@15.1.6': {}
1219 |
1220 | '@next/swc-darwin-arm64@15.1.6':
1221 | optional: true
1222 |
1223 | '@next/swc-darwin-x64@15.1.6':
1224 | optional: true
1225 |
1226 | '@next/swc-linux-arm64-gnu@15.1.6':
1227 | optional: true
1228 |
1229 | '@next/swc-linux-arm64-musl@15.1.6':
1230 | optional: true
1231 |
1232 | '@next/swc-linux-x64-gnu@15.1.6':
1233 | optional: true
1234 |
1235 | '@next/swc-linux-x64-musl@15.1.6':
1236 | optional: true
1237 |
1238 | '@next/swc-win32-arm64-msvc@15.1.6':
1239 | optional: true
1240 |
1241 | '@next/swc-win32-x64-msvc@15.1.6':
1242 | optional: true
1243 |
1244 | '@nodelib/fs.scandir@2.1.5':
1245 | dependencies:
1246 | '@nodelib/fs.stat': 2.0.5
1247 | run-parallel: 1.2.0
1248 |
1249 | '@nodelib/fs.stat@2.0.5': {}
1250 |
1251 | '@nodelib/fs.walk@1.2.8':
1252 | dependencies:
1253 | '@nodelib/fs.scandir': 2.1.5
1254 | fastq: 1.18.0
1255 |
1256 | '@panva/hkdf@1.2.1': {}
1257 |
1258 | '@pkgjs/parseargs@0.11.0':
1259 | optional: true
1260 |
1261 | '@swc/counter@0.1.3': {}
1262 |
1263 | '@swc/helpers@0.5.15':
1264 | dependencies:
1265 | tslib: 2.8.1
1266 |
1267 | '@tailwindcss/forms@0.5.10(tailwindcss@3.4.17)':
1268 | dependencies:
1269 | mini-svg-data-uri: 1.4.4
1270 | tailwindcss: 3.4.17
1271 |
1272 | '@types/bcrypt@5.0.2':
1273 | dependencies:
1274 | '@types/node': 22.10.7
1275 |
1276 | '@types/cookie@0.6.0': {}
1277 |
1278 | '@types/node@22.10.7':
1279 | dependencies:
1280 | undici-types: 6.20.0
1281 |
1282 | '@types/react-dom@19.0.3(@types/react@19.0.7)':
1283 | dependencies:
1284 | '@types/react': 19.0.7
1285 |
1286 | '@types/react@19.0.7':
1287 | dependencies:
1288 | csstype: 3.1.3
1289 |
1290 | abbrev@1.1.1: {}
1291 |
1292 | agent-base@6.0.2:
1293 | dependencies:
1294 | debug: 4.4.0
1295 | transitivePeerDependencies:
1296 | - supports-color
1297 |
1298 | ansi-regex@5.0.1: {}
1299 |
1300 | ansi-regex@6.1.0: {}
1301 |
1302 | ansi-styles@4.3.0:
1303 | dependencies:
1304 | color-convert: 2.0.1
1305 |
1306 | ansi-styles@6.2.1: {}
1307 |
1308 | any-promise@1.3.0: {}
1309 |
1310 | anymatch@3.1.3:
1311 | dependencies:
1312 | normalize-path: 3.0.0
1313 | picomatch: 2.3.1
1314 |
1315 | aproba@2.0.0: {}
1316 |
1317 | are-we-there-yet@2.0.0:
1318 | dependencies:
1319 | delegates: 1.0.0
1320 | readable-stream: 3.6.2
1321 |
1322 | arg@5.0.2: {}
1323 |
1324 | autoprefixer@10.4.20(postcss@8.5.1):
1325 | dependencies:
1326 | browserslist: 4.24.4
1327 | caniuse-lite: 1.0.30001695
1328 | fraction.js: 4.3.7
1329 | normalize-range: 0.1.2
1330 | picocolors: 1.1.1
1331 | postcss: 8.5.1
1332 | postcss-value-parser: 4.2.0
1333 |
1334 | balanced-match@1.0.2: {}
1335 |
1336 | bcrypt@5.1.1:
1337 | dependencies:
1338 | '@mapbox/node-pre-gyp': 1.0.11
1339 | node-addon-api: 5.1.0
1340 | transitivePeerDependencies:
1341 | - encoding
1342 | - supports-color
1343 |
1344 | binary-extensions@2.3.0: {}
1345 |
1346 | brace-expansion@1.1.11:
1347 | dependencies:
1348 | balanced-match: 1.0.2
1349 | concat-map: 0.0.1
1350 |
1351 | brace-expansion@2.0.1:
1352 | dependencies:
1353 | balanced-match: 1.0.2
1354 |
1355 | braces@3.0.3:
1356 | dependencies:
1357 | fill-range: 7.1.1
1358 |
1359 | browserslist@4.24.4:
1360 | dependencies:
1361 | caniuse-lite: 1.0.30001695
1362 | electron-to-chromium: 1.5.83
1363 | node-releases: 2.0.19
1364 | update-browserslist-db: 1.1.2(browserslist@4.24.4)
1365 |
1366 | busboy@1.6.0:
1367 | dependencies:
1368 | streamsearch: 1.1.0
1369 |
1370 | camelcase-css@2.0.1: {}
1371 |
1372 | caniuse-lite@1.0.30001695: {}
1373 |
1374 | chokidar@3.6.0:
1375 | dependencies:
1376 | anymatch: 3.1.3
1377 | braces: 3.0.3
1378 | glob-parent: 5.1.2
1379 | is-binary-path: 2.1.0
1380 | is-glob: 4.0.3
1381 | normalize-path: 3.0.0
1382 | readdirp: 3.6.0
1383 | optionalDependencies:
1384 | fsevents: 2.3.3
1385 |
1386 | chownr@2.0.0: {}
1387 |
1388 | client-only@0.0.1: {}
1389 |
1390 | clsx@2.1.1: {}
1391 |
1392 | color-convert@2.0.1:
1393 | dependencies:
1394 | color-name: 1.1.4
1395 |
1396 | color-name@1.1.4: {}
1397 |
1398 | color-string@1.9.1:
1399 | dependencies:
1400 | color-name: 1.1.4
1401 | simple-swizzle: 0.2.2
1402 | optional: true
1403 |
1404 | color-support@1.1.3: {}
1405 |
1406 | color@4.2.3:
1407 | dependencies:
1408 | color-convert: 2.0.1
1409 | color-string: 1.9.1
1410 | optional: true
1411 |
1412 | commander@4.1.1: {}
1413 |
1414 | concat-map@0.0.1: {}
1415 |
1416 | console-control-strings@1.1.0: {}
1417 |
1418 | cookie@0.7.1: {}
1419 |
1420 | cross-spawn@7.0.6:
1421 | dependencies:
1422 | path-key: 3.1.1
1423 | shebang-command: 2.0.0
1424 | which: 2.0.2
1425 |
1426 | cssesc@3.0.0: {}
1427 |
1428 | csstype@3.1.3: {}
1429 |
1430 | debug@4.4.0:
1431 | dependencies:
1432 | ms: 2.1.3
1433 |
1434 | delegates@1.0.0: {}
1435 |
1436 | detect-libc@2.0.3: {}
1437 |
1438 | didyoumean@1.2.2: {}
1439 |
1440 | dlv@1.1.3: {}
1441 |
1442 | eastasianwidth@0.2.0: {}
1443 |
1444 | electron-to-chromium@1.5.83: {}
1445 |
1446 | emoji-regex@8.0.0: {}
1447 |
1448 | emoji-regex@9.2.2: {}
1449 |
1450 | escalade@3.2.0: {}
1451 |
1452 | fast-glob@3.3.3:
1453 | dependencies:
1454 | '@nodelib/fs.stat': 2.0.5
1455 | '@nodelib/fs.walk': 1.2.8
1456 | glob-parent: 5.1.2
1457 | merge2: 1.4.1
1458 | micromatch: 4.0.8
1459 |
1460 | fastq@1.18.0:
1461 | dependencies:
1462 | reusify: 1.0.4
1463 |
1464 | fill-range@7.1.1:
1465 | dependencies:
1466 | to-regex-range: 5.0.1
1467 |
1468 | foreground-child@3.3.0:
1469 | dependencies:
1470 | cross-spawn: 7.0.6
1471 | signal-exit: 4.1.0
1472 |
1473 | fraction.js@4.3.7: {}
1474 |
1475 | fs-minipass@2.1.0:
1476 | dependencies:
1477 | minipass: 3.3.6
1478 |
1479 | fs.realpath@1.0.0: {}
1480 |
1481 | fsevents@2.3.3:
1482 | optional: true
1483 |
1484 | function-bind@1.1.2: {}
1485 |
1486 | gauge@3.0.2:
1487 | dependencies:
1488 | aproba: 2.0.0
1489 | color-support: 1.1.3
1490 | console-control-strings: 1.1.0
1491 | has-unicode: 2.0.1
1492 | object-assign: 4.1.1
1493 | signal-exit: 3.0.7
1494 | string-width: 4.2.3
1495 | strip-ansi: 6.0.1
1496 | wide-align: 1.1.5
1497 |
1498 | glob-parent@5.1.2:
1499 | dependencies:
1500 | is-glob: 4.0.3
1501 |
1502 | glob-parent@6.0.2:
1503 | dependencies:
1504 | is-glob: 4.0.3
1505 |
1506 | glob@10.4.5:
1507 | dependencies:
1508 | foreground-child: 3.3.0
1509 | jackspeak: 3.4.3
1510 | minimatch: 9.0.5
1511 | minipass: 7.1.2
1512 | package-json-from-dist: 1.0.1
1513 | path-scurry: 1.11.1
1514 |
1515 | glob@7.2.3:
1516 | dependencies:
1517 | fs.realpath: 1.0.0
1518 | inflight: 1.0.6
1519 | inherits: 2.0.4
1520 | minimatch: 3.1.2
1521 | once: 1.4.0
1522 | path-is-absolute: 1.0.1
1523 |
1524 | has-unicode@2.0.1: {}
1525 |
1526 | hasown@2.0.2:
1527 | dependencies:
1528 | function-bind: 1.1.2
1529 |
1530 | https-proxy-agent@5.0.1:
1531 | dependencies:
1532 | agent-base: 6.0.2
1533 | debug: 4.4.0
1534 | transitivePeerDependencies:
1535 | - supports-color
1536 |
1537 | inflight@1.0.6:
1538 | dependencies:
1539 | once: 1.4.0
1540 | wrappy: 1.0.2
1541 |
1542 | inherits@2.0.4: {}
1543 |
1544 | is-arrayish@0.3.2:
1545 | optional: true
1546 |
1547 | is-binary-path@2.1.0:
1548 | dependencies:
1549 | binary-extensions: 2.3.0
1550 |
1551 | is-core-module@2.16.1:
1552 | dependencies:
1553 | hasown: 2.0.2
1554 |
1555 | is-extglob@2.1.1: {}
1556 |
1557 | is-fullwidth-code-point@3.0.0: {}
1558 |
1559 | is-glob@4.0.3:
1560 | dependencies:
1561 | is-extglob: 2.1.1
1562 |
1563 | is-number@7.0.0: {}
1564 |
1565 | isexe@2.0.0: {}
1566 |
1567 | jackspeak@3.4.3:
1568 | dependencies:
1569 | '@isaacs/cliui': 8.0.2
1570 | optionalDependencies:
1571 | '@pkgjs/parseargs': 0.11.0
1572 |
1573 | jiti@1.21.7: {}
1574 |
1575 | jose@5.9.6: {}
1576 |
1577 | lilconfig@3.1.3: {}
1578 |
1579 | lines-and-columns@1.2.4: {}
1580 |
1581 | lru-cache@10.4.3: {}
1582 |
1583 | make-dir@3.1.0:
1584 | dependencies:
1585 | semver: 6.3.1
1586 |
1587 | merge2@1.4.1: {}
1588 |
1589 | micromatch@4.0.8:
1590 | dependencies:
1591 | braces: 3.0.3
1592 | picomatch: 2.3.1
1593 |
1594 | mini-svg-data-uri@1.4.4: {}
1595 |
1596 | minimatch@3.1.2:
1597 | dependencies:
1598 | brace-expansion: 1.1.11
1599 |
1600 | minimatch@9.0.5:
1601 | dependencies:
1602 | brace-expansion: 2.0.1
1603 |
1604 | minipass@3.3.6:
1605 | dependencies:
1606 | yallist: 4.0.0
1607 |
1608 | minipass@5.0.0: {}
1609 |
1610 | minipass@7.1.2: {}
1611 |
1612 | minizlib@2.1.2:
1613 | dependencies:
1614 | minipass: 3.3.6
1615 | yallist: 4.0.0
1616 |
1617 | mkdirp@1.0.4: {}
1618 |
1619 | ms@2.1.3: {}
1620 |
1621 | mz@2.7.0:
1622 | dependencies:
1623 | any-promise: 1.3.0
1624 | object-assign: 4.1.1
1625 | thenify-all: 1.6.0
1626 |
1627 | nanoid@3.3.8: {}
1628 |
1629 | next-auth@5.0.0-beta.25(next@15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0):
1630 | dependencies:
1631 | '@auth/core': 0.37.2
1632 | next: 15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
1633 | react: 19.0.0
1634 |
1635 | next@15.1.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
1636 | dependencies:
1637 | '@next/env': 15.1.6
1638 | '@swc/counter': 0.1.3
1639 | '@swc/helpers': 0.5.15
1640 | busboy: 1.6.0
1641 | caniuse-lite: 1.0.30001695
1642 | postcss: 8.4.31
1643 | react: 19.0.0
1644 | react-dom: 19.0.0(react@19.0.0)
1645 | styled-jsx: 5.1.6(react@19.0.0)
1646 | optionalDependencies:
1647 | '@next/swc-darwin-arm64': 15.1.6
1648 | '@next/swc-darwin-x64': 15.1.6
1649 | '@next/swc-linux-arm64-gnu': 15.1.6
1650 | '@next/swc-linux-arm64-musl': 15.1.6
1651 | '@next/swc-linux-x64-gnu': 15.1.6
1652 | '@next/swc-linux-x64-musl': 15.1.6
1653 | '@next/swc-win32-arm64-msvc': 15.1.6
1654 | '@next/swc-win32-x64-msvc': 15.1.6
1655 | sharp: 0.33.5
1656 | transitivePeerDependencies:
1657 | - '@babel/core'
1658 | - babel-plugin-macros
1659 |
1660 | node-addon-api@5.1.0: {}
1661 |
1662 | node-fetch@2.7.0:
1663 | dependencies:
1664 | whatwg-url: 5.0.0
1665 |
1666 | node-releases@2.0.19: {}
1667 |
1668 | nopt@5.0.0:
1669 | dependencies:
1670 | abbrev: 1.1.1
1671 |
1672 | normalize-path@3.0.0: {}
1673 |
1674 | normalize-range@0.1.2: {}
1675 |
1676 | npmlog@5.0.1:
1677 | dependencies:
1678 | are-we-there-yet: 2.0.0
1679 | console-control-strings: 1.1.0
1680 | gauge: 3.0.2
1681 | set-blocking: 2.0.0
1682 |
1683 | oauth4webapi@3.1.4: {}
1684 |
1685 | object-assign@4.1.1: {}
1686 |
1687 | object-hash@3.0.0: {}
1688 |
1689 | once@1.4.0:
1690 | dependencies:
1691 | wrappy: 1.0.2
1692 |
1693 | package-json-from-dist@1.0.1: {}
1694 |
1695 | path-is-absolute@1.0.1: {}
1696 |
1697 | path-key@3.1.1: {}
1698 |
1699 | path-parse@1.0.7: {}
1700 |
1701 | path-scurry@1.11.1:
1702 | dependencies:
1703 | lru-cache: 10.4.3
1704 | minipass: 7.1.2
1705 |
1706 | picocolors@1.1.1: {}
1707 |
1708 | picomatch@2.3.1: {}
1709 |
1710 | pify@2.3.0: {}
1711 |
1712 | pirates@4.0.6: {}
1713 |
1714 | postcss-import@15.1.0(postcss@8.5.1):
1715 | dependencies:
1716 | postcss: 8.5.1
1717 | postcss-value-parser: 4.2.0
1718 | read-cache: 1.0.0
1719 | resolve: 1.22.10
1720 |
1721 | postcss-js@4.0.1(postcss@8.5.1):
1722 | dependencies:
1723 | camelcase-css: 2.0.1
1724 | postcss: 8.5.1
1725 |
1726 | postcss-load-config@4.0.2(postcss@8.5.1):
1727 | dependencies:
1728 | lilconfig: 3.1.3
1729 | yaml: 2.7.0
1730 | optionalDependencies:
1731 | postcss: 8.5.1
1732 |
1733 | postcss-nested@6.2.0(postcss@8.5.1):
1734 | dependencies:
1735 | postcss: 8.5.1
1736 | postcss-selector-parser: 6.1.2
1737 |
1738 | postcss-selector-parser@6.1.2:
1739 | dependencies:
1740 | cssesc: 3.0.0
1741 | util-deprecate: 1.0.2
1742 |
1743 | postcss-value-parser@4.2.0: {}
1744 |
1745 | postcss@8.4.31:
1746 | dependencies:
1747 | nanoid: 3.3.8
1748 | picocolors: 1.1.1
1749 | source-map-js: 1.2.1
1750 |
1751 | postcss@8.5.1:
1752 | dependencies:
1753 | nanoid: 3.3.8
1754 | picocolors: 1.1.1
1755 | source-map-js: 1.2.1
1756 |
1757 | postgres@3.4.5: {}
1758 |
1759 | preact-render-to-string@5.2.3(preact@10.11.3):
1760 | dependencies:
1761 | preact: 10.11.3
1762 | pretty-format: 3.8.0
1763 |
1764 | preact@10.11.3: {}
1765 |
1766 | pretty-format@3.8.0: {}
1767 |
1768 | queue-microtask@1.2.3: {}
1769 |
1770 | react-dom@19.0.0(react@19.0.0):
1771 | dependencies:
1772 | react: 19.0.0
1773 | scheduler: 0.25.0
1774 |
1775 | react@19.0.0: {}
1776 |
1777 | read-cache@1.0.0:
1778 | dependencies:
1779 | pify: 2.3.0
1780 |
1781 | readable-stream@3.6.2:
1782 | dependencies:
1783 | inherits: 2.0.4
1784 | string_decoder: 1.3.0
1785 | util-deprecate: 1.0.2
1786 |
1787 | readdirp@3.6.0:
1788 | dependencies:
1789 | picomatch: 2.3.1
1790 |
1791 | resolve@1.22.10:
1792 | dependencies:
1793 | is-core-module: 2.16.1
1794 | path-parse: 1.0.7
1795 | supports-preserve-symlinks-flag: 1.0.0
1796 |
1797 | reusify@1.0.4: {}
1798 |
1799 | rimraf@3.0.2:
1800 | dependencies:
1801 | glob: 7.2.3
1802 |
1803 | run-parallel@1.2.0:
1804 | dependencies:
1805 | queue-microtask: 1.2.3
1806 |
1807 | safe-buffer@5.2.1: {}
1808 |
1809 | scheduler@0.25.0: {}
1810 |
1811 | semver@6.3.1: {}
1812 |
1813 | semver@7.6.3: {}
1814 |
1815 | set-blocking@2.0.0: {}
1816 |
1817 | sharp@0.33.5:
1818 | dependencies:
1819 | color: 4.2.3
1820 | detect-libc: 2.0.3
1821 | semver: 7.6.3
1822 | optionalDependencies:
1823 | '@img/sharp-darwin-arm64': 0.33.5
1824 | '@img/sharp-darwin-x64': 0.33.5
1825 | '@img/sharp-libvips-darwin-arm64': 1.0.4
1826 | '@img/sharp-libvips-darwin-x64': 1.0.4
1827 | '@img/sharp-libvips-linux-arm': 1.0.5
1828 | '@img/sharp-libvips-linux-arm64': 1.0.4
1829 | '@img/sharp-libvips-linux-s390x': 1.0.4
1830 | '@img/sharp-libvips-linux-x64': 1.0.4
1831 | '@img/sharp-libvips-linuxmusl-arm64': 1.0.4
1832 | '@img/sharp-libvips-linuxmusl-x64': 1.0.4
1833 | '@img/sharp-linux-arm': 0.33.5
1834 | '@img/sharp-linux-arm64': 0.33.5
1835 | '@img/sharp-linux-s390x': 0.33.5
1836 | '@img/sharp-linux-x64': 0.33.5
1837 | '@img/sharp-linuxmusl-arm64': 0.33.5
1838 | '@img/sharp-linuxmusl-x64': 0.33.5
1839 | '@img/sharp-wasm32': 0.33.5
1840 | '@img/sharp-win32-ia32': 0.33.5
1841 | '@img/sharp-win32-x64': 0.33.5
1842 | optional: true
1843 |
1844 | shebang-command@2.0.0:
1845 | dependencies:
1846 | shebang-regex: 3.0.0
1847 |
1848 | shebang-regex@3.0.0: {}
1849 |
1850 | signal-exit@3.0.7: {}
1851 |
1852 | signal-exit@4.1.0: {}
1853 |
1854 | simple-swizzle@0.2.2:
1855 | dependencies:
1856 | is-arrayish: 0.3.2
1857 | optional: true
1858 |
1859 | source-map-js@1.2.1: {}
1860 |
1861 | streamsearch@1.1.0: {}
1862 |
1863 | string-width@4.2.3:
1864 | dependencies:
1865 | emoji-regex: 8.0.0
1866 | is-fullwidth-code-point: 3.0.0
1867 | strip-ansi: 6.0.1
1868 |
1869 | string-width@5.1.2:
1870 | dependencies:
1871 | eastasianwidth: 0.2.0
1872 | emoji-regex: 9.2.2
1873 | strip-ansi: 7.1.0
1874 |
1875 | string_decoder@1.3.0:
1876 | dependencies:
1877 | safe-buffer: 5.2.1
1878 |
1879 | strip-ansi@6.0.1:
1880 | dependencies:
1881 | ansi-regex: 5.0.1
1882 |
1883 | strip-ansi@7.1.0:
1884 | dependencies:
1885 | ansi-regex: 6.1.0
1886 |
1887 | styled-jsx@5.1.6(react@19.0.0):
1888 | dependencies:
1889 | client-only: 0.0.1
1890 | react: 19.0.0
1891 |
1892 | sucrase@3.35.0:
1893 | dependencies:
1894 | '@jridgewell/gen-mapping': 0.3.8
1895 | commander: 4.1.1
1896 | glob: 10.4.5
1897 | lines-and-columns: 1.2.4
1898 | mz: 2.7.0
1899 | pirates: 4.0.6
1900 | ts-interface-checker: 0.1.13
1901 |
1902 | supports-preserve-symlinks-flag@1.0.0: {}
1903 |
1904 | tailwindcss@3.4.17:
1905 | dependencies:
1906 | '@alloc/quick-lru': 5.2.0
1907 | arg: 5.0.2
1908 | chokidar: 3.6.0
1909 | didyoumean: 1.2.2
1910 | dlv: 1.1.3
1911 | fast-glob: 3.3.3
1912 | glob-parent: 6.0.2
1913 | is-glob: 4.0.3
1914 | jiti: 1.21.7
1915 | lilconfig: 3.1.3
1916 | micromatch: 4.0.8
1917 | normalize-path: 3.0.0
1918 | object-hash: 3.0.0
1919 | picocolors: 1.1.1
1920 | postcss: 8.5.1
1921 | postcss-import: 15.1.0(postcss@8.5.1)
1922 | postcss-js: 4.0.1(postcss@8.5.1)
1923 | postcss-load-config: 4.0.2(postcss@8.5.1)
1924 | postcss-nested: 6.2.0(postcss@8.5.1)
1925 | postcss-selector-parser: 6.1.2
1926 | resolve: 1.22.10
1927 | sucrase: 3.35.0
1928 | transitivePeerDependencies:
1929 | - ts-node
1930 |
1931 | tar@6.2.1:
1932 | dependencies:
1933 | chownr: 2.0.0
1934 | fs-minipass: 2.1.0
1935 | minipass: 5.0.0
1936 | minizlib: 2.1.2
1937 | mkdirp: 1.0.4
1938 | yallist: 4.0.0
1939 |
1940 | thenify-all@1.6.0:
1941 | dependencies:
1942 | thenify: 3.3.1
1943 |
1944 | thenify@3.3.1:
1945 | dependencies:
1946 | any-promise: 1.3.0
1947 |
1948 | to-regex-range@5.0.1:
1949 | dependencies:
1950 | is-number: 7.0.0
1951 |
1952 | tr46@0.0.3: {}
1953 |
1954 | ts-interface-checker@0.1.13: {}
1955 |
1956 | tslib@2.8.1: {}
1957 |
1958 | typescript@5.7.3: {}
1959 |
1960 | undici-types@6.20.0: {}
1961 |
1962 | update-browserslist-db@1.1.2(browserslist@4.24.4):
1963 | dependencies:
1964 | browserslist: 4.24.4
1965 | escalade: 3.2.0
1966 | picocolors: 1.1.1
1967 |
1968 | use-debounce@10.0.4(react@19.0.0):
1969 | dependencies:
1970 | react: 19.0.0
1971 |
1972 | util-deprecate@1.0.2: {}
1973 |
1974 | webidl-conversions@3.0.1: {}
1975 |
1976 | whatwg-url@5.0.0:
1977 | dependencies:
1978 | tr46: 0.0.3
1979 | webidl-conversions: 3.0.1
1980 |
1981 | which@2.0.2:
1982 | dependencies:
1983 | isexe: 2.0.0
1984 |
1985 | wide-align@1.1.5:
1986 | dependencies:
1987 | string-width: 4.2.3
1988 |
1989 | wrap-ansi@7.0.0:
1990 | dependencies:
1991 | ansi-styles: 4.3.0
1992 | string-width: 4.2.3
1993 | strip-ansi: 6.0.1
1994 |
1995 | wrap-ansi@8.1.0:
1996 | dependencies:
1997 | ansi-styles: 6.2.1
1998 | string-width: 5.1.2
1999 | strip-ansi: 7.1.0
2000 |
2001 | wrappy@1.0.2: {}
2002 |
2003 | yallist@4.0.0: {}
2004 |
2005 | yaml@2.7.0: {}
2006 |
2007 | zod@3.24.1: {}
2008 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/public/customers/amy-burns.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dmytrozaiets81/nextjs-learn/f371f123ce3bc566ec6bde86c03334a93dfc7242/public/customers/amy-burns.png
--------------------------------------------------------------------------------
/public/customers/balazs-orban.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dmytrozaiets81/nextjs-learn/f371f123ce3bc566ec6bde86c03334a93dfc7242/public/customers/balazs-orban.png
--------------------------------------------------------------------------------
/public/customers/delba-de-oliveira.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dmytrozaiets81/nextjs-learn/f371f123ce3bc566ec6bde86c03334a93dfc7242/public/customers/delba-de-oliveira.png
--------------------------------------------------------------------------------
/public/customers/evil-rabbit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dmytrozaiets81/nextjs-learn/f371f123ce3bc566ec6bde86c03334a93dfc7242/public/customers/evil-rabbit.png
--------------------------------------------------------------------------------
/public/customers/lee-robinson.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dmytrozaiets81/nextjs-learn/f371f123ce3bc566ec6bde86c03334a93dfc7242/public/customers/lee-robinson.png
--------------------------------------------------------------------------------
/public/customers/michael-novotny.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dmytrozaiets81/nextjs-learn/f371f123ce3bc566ec6bde86c03334a93dfc7242/public/customers/michael-novotny.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dmytrozaiets81/nextjs-learn/f371f123ce3bc566ec6bde86c03334a93dfc7242/public/favicon.ico
--------------------------------------------------------------------------------
/public/hero-desktop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dmytrozaiets81/nextjs-learn/f371f123ce3bc566ec6bde86c03334a93dfc7242/public/hero-desktop.png
--------------------------------------------------------------------------------
/public/hero-mobile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dmytrozaiets81/nextjs-learn/f371f123ce3bc566ec6bde86c03334a93dfc7242/public/hero-mobile.png
--------------------------------------------------------------------------------
/public/opengraph-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dmytrozaiets81/nextjs-learn/f371f123ce3bc566ec6bde86c03334a93dfc7242/public/opengraph-image.png
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'tailwindcss';
2 |
3 | const config: Config = {
4 | content: [
5 | './pages/**/*.{js,ts,jsx,tsx,mdx}',
6 | './components/**/*.{js,ts,jsx,tsx,mdx}',
7 | './app/**/*.{js,ts,jsx,tsx,mdx}',
8 | ],
9 | theme: {
10 | extend: {
11 | gridTemplateColumns: {
12 | '13': 'repeat(13, minmax(0, 1fr))',
13 | },
14 | colors: {
15 | blue: {
16 | 400: '#2589FE',
17 | 500: '#0070F3',
18 | 600: '#2F6FEB',
19 | },
20 | },
21 | },
22 | keyframes: {
23 | shimmer: {
24 | '100%': {
25 | transform: 'translateX(100%)',
26 | },
27 | },
28 | },
29 | },
30 | plugins: [require('@tailwindcss/forms')],
31 | };
32 | export default config;
33 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2017",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "noEmit": true,
9 | "esModuleInterop": true,
10 | "module": "esnext",
11 | "moduleResolution": "bundler",
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "jsx": "preserve",
15 | "incremental": true,
16 | "plugins": [
17 | {
18 | "name": "next"
19 | }
20 | ],
21 | "baseUrl": ".",
22 | "paths": {
23 | "@/*": ["./*"]
24 | }
25 | },
26 | "include": [
27 | "next-env.d.ts",
28 | "**/*.ts",
29 | "**/*.tsx",
30 | ".next/types/**/*.ts",
31 | "app/lib/placeholder-data.ts",
32 | "scripts/seed.js"
33 | ],
34 | "exclude": ["node_modules"]
35 | }
36 |
--------------------------------------------------------------------------------