mirror of
https://github.com/spliit-app/spliit.git
synced 2026-03-09 13:49:04 +01:00
Upgrade Next.js to 14.1.0
This commit is contained in:
1064
package-lock.json
generated
1064
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -37,13 +37,14 @@
|
|||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"lucide-react": "^0.290.0",
|
"lucide-react": "^0.290.0",
|
||||||
"nanoid": "^5.0.4",
|
"nanoid": "^5.0.4",
|
||||||
"next": "^14.0.4",
|
"next": "^14.1.0",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"next13-progressbar": "^1.1.1",
|
"next13-progressbar": "^1.1.1",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hook-form": "^7.47.0",
|
"react-hook-form": "^7.47.0",
|
||||||
|
"sharp": "^0.33.2",
|
||||||
"tailwind-merge": "^1.14.0",
|
"tailwind-merge": "^1.14.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"ts-pattern": "^5.0.6",
|
"ts-pattern": "^5.0.6",
|
||||||
@@ -56,13 +57,13 @@
|
|||||||
"@types/content-disposition": "^0.5.8",
|
"@types/content-disposition": "^0.5.8",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/pg": "^8.10.9",
|
"@types/pg": "^8.10.9",
|
||||||
"@types/react": "^18",
|
"@types/react": "^18.2.48",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18.2.18",
|
||||||
"@types/uuid": "^9.0.6",
|
"@types/uuid": "^9.0.6",
|
||||||
"autoprefixer": "^10",
|
"autoprefixer": "^10",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"eslint": "^8",
|
"eslint": "^8",
|
||||||
"eslint-config-next": "^14.0.4",
|
"eslint-config-next": "^14.1.0",
|
||||||
"postcss": "^8",
|
"postcss": "^8",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"prettier-plugin-organize-imports": "^3.2.3",
|
"prettier-plugin-organize-imports": "^3.2.3",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
import { expenseFormSchema } from '@/lib/schemas'
|
import { expenseFormSchema } from '@/lib/schemas'
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import { notFound, redirect } from 'next/navigation'
|
import { notFound, redirect } from 'next/navigation'
|
||||||
|
import { Suspense } from 'react'
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'Edit expense',
|
title: 'Edit expense',
|
||||||
@@ -39,12 +40,14 @@ export default async function EditExpensePage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ExpenseForm
|
<Suspense>
|
||||||
group={group}
|
<ExpenseForm
|
||||||
expense={expense}
|
group={group}
|
||||||
categories={categories}
|
expense={expense}
|
||||||
onSubmit={updateExpenseAction}
|
categories={categories}
|
||||||
onDelete={deleteExpenseAction}
|
onSubmit={updateExpenseAction}
|
||||||
/>
|
onDelete={deleteExpenseAction}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { createExpense, getCategories, getGroup } from '@/lib/api'
|
|||||||
import { expenseFormSchema } from '@/lib/schemas'
|
import { expenseFormSchema } from '@/lib/schemas'
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import { notFound, redirect } from 'next/navigation'
|
import { notFound, redirect } from 'next/navigation'
|
||||||
|
import { Suspense } from 'react'
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'Create expense',
|
title: 'Create expense',
|
||||||
@@ -25,10 +26,12 @@ export default async function ExpensePage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ExpenseForm
|
<Suspense>
|
||||||
group={group}
|
<ExpenseForm
|
||||||
categories={categories}
|
group={group}
|
||||||
onSubmit={createExpenseAction}
|
categories={categories}
|
||||||
/>
|
onSubmit={createExpenseAction}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ export async function GET(
|
|||||||
req: Request,
|
req: Request,
|
||||||
{ params: { groupId } }: { params: { groupId: string } },
|
{ params: { groupId } }: { params: { groupId: string } },
|
||||||
) {
|
) {
|
||||||
console.log({ groupId })
|
|
||||||
const prisma = await getPrisma()
|
const prisma = await getPrisma()
|
||||||
const group = await prisma.group.findUnique({
|
const group = await prisma.group.findUnique({
|
||||||
where: { id: groupId },
|
where: { id: groupId },
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { getGroup } from '@/lib/api'
|
|||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { notFound } from 'next/navigation'
|
import { notFound } from 'next/navigation'
|
||||||
import { PropsWithChildren } from 'react'
|
import { PropsWithChildren, Suspense } from 'react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
params: {
|
params: {
|
||||||
@@ -41,7 +41,9 @@ export default async function GroupLayout({
|
|||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div className="flex gap-2 justify-between">
|
<div className="flex gap-2 justify-between">
|
||||||
<GroupTabs groupId={groupId} />
|
<Suspense>
|
||||||
|
<GroupTabs groupId={groupId} />
|
||||||
|
</Suspense>
|
||||||
<ShareButton group={group} />
|
<ShareButton group={group} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { PropsWithChildren } from 'react'
|
import { PropsWithChildren, Suspense } from 'react'
|
||||||
|
|
||||||
export default function GroupsLayout({ children }: PropsWithChildren<{}>) {
|
export default function GroupsLayout({ children }: PropsWithChildren<{}>) {
|
||||||
return (
|
return (
|
||||||
<>
|
<Suspense>
|
||||||
<main className="flex-1 max-w-screen-md w-full mx-auto px-4 py-6 flex flex-col gap-6">
|
<main className="flex-1 max-w-screen-md w-full mx-auto px-4 py-6 flex flex-col gap-6">
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
</>
|
</Suspense>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { env } from '@/lib/env'
|
|||||||
import type { Metadata, Viewport } from 'next'
|
import type { Metadata, Viewport } from 'next'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { Suspense } from 'react'
|
||||||
import './globals.css'
|
import './globals.css'
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
@@ -71,7 +72,9 @@ export default function RootLayout({
|
|||||||
enableSystem
|
enableSystem
|
||||||
disableTransitionOnChange
|
disableTransitionOnChange
|
||||||
>
|
>
|
||||||
<ProgressBar />
|
<Suspense>
|
||||||
|
<ProgressBar />
|
||||||
|
</Suspense>
|
||||||
<header className="fixed top-0 left-0 right-0 h-16 flex justify-between bg-white dark:bg-gray-950 bg-opacity-50 dark:bg-opacity-50 p-2 border-b backdrop-blur-sm z-50">
|
<header className="fixed top-0 left-0 right-0 h-16 flex justify-between bg-white dark:bg-gray-950 bg-opacity-50 dark:bg-opacity-50 p-2 border-b backdrop-blur-sm z-50">
|
||||||
<Link
|
<Link
|
||||||
className="flex items-center gap-2 hover:scale-105 transition-transform"
|
className="flex items-center gap-2 hover:scale-105 transition-transform"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Github } from 'lucide-react'
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
|
||||||
// FIX for https://github.com/vercel/next.js/issues/58615
|
// FIX for https://github.com/vercel/next.js/issues/58615
|
||||||
export const dynamic = 'force-dynamic'
|
// export const dynamic = 'force-dynamic'
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import { getGroup } from '@/lib/api'
|
|||||||
import { GroupFormValues, groupFormSchema } from '@/lib/schemas'
|
import { GroupFormValues, groupFormSchema } from '@/lib/schemas'
|
||||||
import { zodResolver } from '@hookform/resolvers/zod'
|
import { zodResolver } from '@hookform/resolvers/zod'
|
||||||
import { Save, Trash2 } from 'lucide-react'
|
import { Save, Trash2 } from 'lucide-react'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
import { useFieldArray, useForm } from 'react-hook-form'
|
import { useFieldArray, useForm } from 'react-hook-form'
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
@@ -68,15 +69,25 @@ export function GroupForm({
|
|||||||
keyName: 'key',
|
keyName: 'key',
|
||||||
})
|
})
|
||||||
|
|
||||||
let activeUser = 'None'
|
const [activeUser, setActiveUser] = useState<string | null>(null)
|
||||||
|
useEffect(() => {
|
||||||
|
if (activeUser === null) {
|
||||||
|
const currentActiveUser =
|
||||||
|
fields.find(
|
||||||
|
(f) => f.id === localStorage.getItem(`${group?.id}-activeUser`),
|
||||||
|
)?.name || 'None'
|
||||||
|
setActiveUser(currentActiveUser)
|
||||||
|
}
|
||||||
|
}, [activeUser, fields, group?.id])
|
||||||
|
|
||||||
const updateActiveUser = () => {
|
const updateActiveUser = () => {
|
||||||
|
if (!activeUser) return
|
||||||
if (group?.id) {
|
if (group?.id) {
|
||||||
const participant = group.participants.find((p) => p.name === activeUser)
|
const participant = group.participants.find((p) => p.name === activeUser)
|
||||||
if (participant?.id) {
|
if (participant?.id) {
|
||||||
localStorage.setItem(`${group.id}-activeUser`, participant.id)
|
localStorage.setItem(`${group.id}-activeUser`, participant.id)
|
||||||
} else {
|
} else {
|
||||||
localStorage.setItem(`${group.id}-newUser`, activeUser)
|
localStorage.setItem(`${group.id}-activeUser`, activeUser)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
localStorage.setItem('newGroup-activeUser', activeUser)
|
localStorage.setItem('newGroup-activeUser', activeUser)
|
||||||
@@ -228,39 +239,35 @@ export function GroupForm({
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="grid sm:grid-cols-2 gap-4">
|
<div className="grid sm:grid-cols-2 gap-4">
|
||||||
<FormItem>
|
{activeUser !== null && (
|
||||||
<FormLabel>Active user</FormLabel>
|
<FormItem>
|
||||||
<FormControl>
|
<FormLabel>Active user</FormLabel>
|
||||||
<Select
|
<FormControl>
|
||||||
onValueChange={(value) => {
|
<Select
|
||||||
activeUser = value
|
onValueChange={(value) => {
|
||||||
}}
|
setActiveUser(value)
|
||||||
defaultValue={
|
}}
|
||||||
fields.find(
|
defaultValue={activeUser}
|
||||||
(f) =>
|
>
|
||||||
f.id ===
|
<SelectTrigger>
|
||||||
localStorage.getItem(`${group?.id}-activeUser`),
|
<SelectValue placeholder="Select a participant" />
|
||||||
)?.name || 'None'
|
</SelectTrigger>
|
||||||
}
|
<SelectContent>
|
||||||
>
|
{[{ name: 'None' }, ...form.watch('participants')]
|
||||||
<SelectTrigger>
|
.filter((item) => item.name.length > 0)
|
||||||
<SelectValue placeholder="Select a participant" />
|
.map(({ name }) => (
|
||||||
</SelectTrigger>
|
<SelectItem key={name} value={name}>
|
||||||
<SelectContent>
|
{name}
|
||||||
{[{ name: 'None' }, ...form.watch('participants')]
|
</SelectItem>
|
||||||
.filter((item) => item.name.length > 0)
|
))}
|
||||||
.map(({ name }) => (
|
</SelectContent>
|
||||||
<SelectItem key={name} value={name}>
|
</Select>
|
||||||
{name}
|
</FormControl>
|
||||||
</SelectItem>
|
<FormDescription>
|
||||||
))}
|
User used as default for paying expenses.
|
||||||
</SelectContent>
|
</FormDescription>
|
||||||
</Select>
|
</FormItem>
|
||||||
</FormControl>
|
)}
|
||||||
<FormDescription>
|
|
||||||
User used as default for paying expenses.
|
|
||||||
</FormDescription>
|
|
||||||
</FormItem>
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
Reference in New Issue
Block a user