diff --git a/.env b/.env
index c1117f5..9cf1821 100644
--- a/.env
+++ b/.env
@@ -1,8 +1,8 @@
# ===================================
# CLOUDINARY
# ===================================
-NEXT_PUBLIC_CLOUD_NAME=dwqknejrz
-NEXT_PUBLIC_UPLOAD_PRESET=ad-app
+NEXT_PUBLIC_CLOUD_NAME=
+NEXT_PUBLIC_UPLOAD_PRESET=
# ===================================
# ===================================
@@ -15,4 +15,4 @@ NEXT_PUBLIC_UPLOAD_PRESET=ad-app
# VERCEL
# ===================================
# NEXT_PUBLIC_PROJECT_HTTP_URL=
-# ===================================
\ No newline at end of file
+# ===================================
diff --git a/package.json b/package.json
index 40afd86..54ec885 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"dependencies": {
"@hookform/resolvers": "^3.3.1",
"@prisma/client": "^5.2.0",
+ "@tanstack/react-query": "^4.35.3",
"@types/react": "18.2.21",
"@types/react-dom": "18.2.7",
"classnames": "^2.3.2",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 82d8e89..f7f7c72 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -3,6 +3,7 @@ lockfileVersion: 5.4
specifiers:
'@hookform/resolvers': ^3.3.1
'@prisma/client': ^5.2.0
+ '@tanstack/react-query': ^4.35.3
'@types/node': 20.5.9
'@types/react': 18.2.21
'@types/react-dom': 18.2.7
@@ -27,6 +28,7 @@ specifiers:
dependencies:
'@hookform/resolvers': 3.3.1_react-hook-form@7.46.1
'@prisma/client': 5.2.0_prisma@5.2.0
+ '@tanstack/react-query': 4.35.3_biqbaboplfbrettd7655fr4n2y
'@types/react': 18.2.21
'@types/react-dom': 18.2.7
classnames: 2.3.2
@@ -319,6 +321,28 @@ packages:
tslib: 2.6.2
dev: false
+ /@tanstack/query-core/4.35.3:
+ resolution: {integrity: sha512-PS+WEjd9wzKTyNjjQymvcOe1yg8f3wYc6mD+vb6CKyZAKvu4sIJwryfqfBULITKCla7P9C4l5e9RXePHvZOZeQ==}
+ dev: false
+
+ /@tanstack/react-query/4.35.3_biqbaboplfbrettd7655fr4n2y:
+ resolution: {integrity: sha512-UgTPioip/rGG3EQilXfA2j4BJkhEQsR+KAbF+KIuvQ7j4MkgnTCJF01SfRpIRNtQTlEfz/+IL7+jP8WA8bFbsw==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
+ react-native: '*'
+ peerDependenciesMeta:
+ react-dom:
+ optional: true
+ react-native:
+ optional: true
+ dependencies:
+ '@tanstack/query-core': 4.35.3
+ react: 18.2.0
+ react-dom: 18.2.0_react@18.2.0
+ use-sync-external-store: 1.2.0_react@18.2.0
+ dev: false
+
/@tsconfig/node10/1.0.9:
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
dev: true
@@ -2672,6 +2696,14 @@ packages:
punycode: 2.3.0
dev: false
+ /use-sync-external-store/1.2.0_react@18.2.0:
+ resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ dependencies:
+ react: 18.2.0
+ dev: false
+
/util-deprecate/1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
dev: false
diff --git a/src/app/add-advertisement/loading.tsx b/src/app/add-advertisement/loading.tsx
index c7bb90d..16693de 100644
--- a/src/app/add-advertisement/loading.tsx
+++ b/src/app/add-advertisement/loading.tsx
@@ -1,8 +1,7 @@
import { AddAdvertisementFormSkeleton } from '@/components/add-advertisement/add-advertisement-form/add-advertisement-form'
import { BreadcrumbSkeleton } from '@/components/general/breadcrumb/breadcrumb'
-import { NextPage } from 'next'
-const Loading: NextPage = () => {
+const Loading = () => {
return (
diff --git a/src/app/add-advertisement/page.tsx b/src/app/add-advertisement/page.tsx
index 6ca3ff6..2f3ea54 100644
--- a/src/app/add-advertisement/page.tsx
+++ b/src/app/add-advertisement/page.tsx
@@ -1,7 +1,6 @@
import AddAdvertisement from '@/components/add-advertisement/add-advertisement'
-import { NextPage } from 'next'
-const AddAdvertisementPage: NextPage = () => {
+const AddAdvertisementPage = () => {
return
}
diff --git a/src/app/api/advertisements/[id]/route.ts b/src/app/api/advertisements/[id]/route.ts
index 7590543..37fbb36 100644
--- a/src/app/api/advertisements/[id]/route.ts
+++ b/src/app/api/advertisements/[id]/route.ts
@@ -2,6 +2,8 @@ import { NextResponse } from 'next/server'
import moment from 'moment-timezone'
import prisma from '@/lib/prisma'
+export const dynamic = 'force-dynamic'
+
export async function PATCH(
request: Request,
{ params }: { params: { id: string } }
diff --git a/src/app/api/advertisements/route.ts b/src/app/api/advertisements/route.ts
index 29c50fb..2414983 100644
--- a/src/app/api/advertisements/route.ts
+++ b/src/app/api/advertisements/route.ts
@@ -1,5 +1,18 @@
import { NextResponse } from 'next/server'
import prisma from '@/lib/prisma'
+export const dynamic = 'force-dynamic'
+
+export async function GET(request: Request) {
+ try {
+ const ads = await prisma.advertisement.findMany({
+ orderBy: [{ lastUpdated: 'desc' }]
+ })
+
+ return NextResponse.json(ads)
+ } catch (error: any) {
+ return new NextResponse(error.message, { status: 500 })
+ }
+}
export async function POST(request: Request) {
try {
diff --git a/src/app/error.tsx b/src/app/error.tsx
index 36c0d77..b13219d 100644
--- a/src/app/error.tsx
+++ b/src/app/error.tsx
@@ -8,7 +8,7 @@ interface Props {
reset: () => void
}
-const Error: React.FC
= ({ error, reset }) => {
+const Error = ({ error, reset }: Props) => {
const [show, setShow] = useState(false)
const showError = () => {
setShow(true)
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 26e6bc2..57d4255 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -5,6 +5,7 @@ import Header from '@/components/layout/header/header'
import { Inter } from 'next/font/google'
import Main from '@/components/layout/main/main'
import type { Metadata } from 'next'
+import { ReactQueryProviders } from '@/context/react-query.context'
import { SortOptionProvider } from '@/context/sort-option.context'
import Toast from '@/components/general/toast/toast'
import { ToastProvider } from '@/context/toast.context'
@@ -19,23 +20,24 @@ export const metadata: Metadata = {
}
}
-
interface Props {
children: React.ReactNode
}
-const RootLayout: React.FC = ({ children }) => {
+const RootLayout = ({ children }: Props) => {
return (
-
-
-
-
- {children}
-
-
-
+
+
+
+
+
+ {children}
+
+
+
+
)
diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx
index 6f0841a..5a310e4 100644
--- a/src/app/not-found.tsx
+++ b/src/app/not-found.tsx
@@ -7,7 +7,7 @@ interface Props {
reset: () => void
}
-const Error: React.FC = ({ error, reset }) => {
+const Error = ({ error, reset }: Props) => {
return (
Sayfa bulunamadı!
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 8ea255b..d7359d5 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,9 +1,6 @@
import HomePage from '@/components/homepage/homepage'
-import { NextPage } from 'next'
-export const dynamic = 'force-dynamic'
-
-const Home: NextPage = () => {
+const Home = () => {
return
}
diff --git a/src/components/add-advertisement/add-advertisement-form/add-advertisement-form.tsx b/src/components/add-advertisement/add-advertisement-form/add-advertisement-form.tsx
index 9758ed4..ca0448e 100644
--- a/src/components/add-advertisement/add-advertisement-form/add-advertisement-form.tsx
+++ b/src/components/add-advertisement/add-advertisement-form/add-advertisement-form.tsx
@@ -10,16 +10,19 @@ import { checkFile, uploadToCloudinary } from '@/utils/helpers'
import { Button } from '@/components/general/button/button'
import Icon from '@/components/general/icon/icon'
import { Skeleton } from '@/components/general/skeleton/skeleton'
+import { addAdvertisements } from '@/lib/query-service'
import classNames from 'classnames'
import styles from './styles.module.scss'
import { useForm } from 'react-hook-form'
+import { useMutation } from '@tanstack/react-query'
+import { useQueryClientInstance } from '@/context/query-client.context'
// Because of using App dir, we need to use next/navigation instead of next/router
// See: https://nextjs.org/docs/messages/next-router-not-mounted
import { useRouter } from 'next/navigation'
import { useToast } from '@/hooks/use-toast'
import { yupResolver } from '@hookform/resolvers/yup'
-export const AddAdvertisementForm: React.FC = () => {
+export const AddAdvertisementForm = () => {
const [imageUploadLabel, setImageUploadLabel] = useState('Yükle')
const [isLoading, setIsLoading] = useState(false)
const formOptions = {
@@ -41,6 +44,22 @@ export const AddAdvertisementForm: React.FC = () => {
} = useForm(formOptions)
const { errors } = formState
+ const { queryClient } = useQueryClientInstance()
+
+ const { isLoading: dataIsLoading, mutate } = useMutation({
+ mutationFn: addAdvertisements,
+ onSuccess: () => {
+ showToast(
+ 'İlan başarıyla kaydedilmiştir. Ana sayfaya yönlendiriliyorsunuz',
+ 'success'
+ )
+ queryClient.invalidateQueries({ queryKey: ['ads'] })
+ },
+ onError: () => {
+ showToast('İlan eklenirken bir sorun oluştu.', 'error')
+ }
+ })
+
const handleFileChange = async (e: ChangeEvent) => {
setIsLoading(true)
@@ -66,25 +85,15 @@ export const AddAdvertisementForm: React.FC = () => {
}
const onSubmit = async () => {
- const response = await fetch('/api/advertisements', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ ...watch() })
- })
-
- if (response.ok) {
- showToast(
- 'İlan başarıyla kaydedilmiştir. Ana sayfaya yönlendiriliyorsunuz',
- 'success'
- )
- } else {
- const error = await response.text()
- showToast(error, 'error')
- }
- reset()
- setImageUploadLabel('Yükle')
- router.refresh()
- router.push('/')
+ mutate(
+ { ...watch() },
+ {
+ onSuccess: () => {
+ setImageUploadLabel('Yükle')
+ router.push('/')
+ }
+ }
+ )
}
return (
@@ -164,7 +173,7 @@ export const AddAdvertisementForm: React.FC = () => {