feat: add file upload
feat: add db connection
This commit is contained in:
parent
efdf39ba9a
commit
d5a267fead
184
package-lock.json
generated
184
package-lock.json
generated
|
@ -19,9 +19,11 @@
|
|||
"@types/react": "^18.2.47",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@vercel/blob": "^0.19.0",
|
||||
"@vercel/postgres-kysely": "^0.7.1",
|
||||
"astro": "^4.1.2",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.0",
|
||||
"kysely": "^0.27.2",
|
||||
"lucide-react": "^0.309.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
@ -1083,6 +1085,14 @@
|
|||
"node-pre-gyp": "bin/node-pre-gyp"
|
||||
}
|
||||
},
|
||||
"node_modules/@neondatabase/serverless": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@neondatabase/serverless/-/serverless-0.7.2.tgz",
|
||||
"integrity": "sha512-wU3WA2uTyNO7wjPs3Mg0G01jztAxUxzd9/mskMmtPwPTjf7JKWi9AW5/puOGXLxmZ9PVgRFeBVRVYq5nBPhsCg==",
|
||||
"dependencies": {
|
||||
"@types/pg": "8.6.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
@ -1499,6 +1509,24 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz",
|
||||
"integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz",
|
||||
"integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/pg": {
|
||||
"version": "8.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.6.tgz",
|
||||
"integrity": "sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"pg-protocol": "*",
|
||||
"pg-types": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
|
||||
|
@ -1626,6 +1654,34 @@
|
|||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@vercel/postgres": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/postgres/-/postgres-0.7.1.tgz",
|
||||
"integrity": "sha512-QTOQrzxkB+H37HrQ8n7uxuXQb9Q4/L8sibMuO98dNvkIv79iDmiy/jJ1rAcwn+D/6In3LnXAoH6S+XL6rpi8tQ==",
|
||||
"dependencies": {
|
||||
"@neondatabase/serverless": "0.7.2",
|
||||
"bufferutil": "4.0.8",
|
||||
"utf-8-validate": "6.0.3",
|
||||
"ws": "8.14.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@vercel/postgres-kysely": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/postgres-kysely/-/postgres-kysely-0.7.1.tgz",
|
||||
"integrity": "sha512-HjWRWwreJTLfOP8Kio/naflXCqXY9mL7adn/Tv62XCjBwE6DNutU8LoDH072vt2A2Xqv0nmT794ORTidFLnvCg==",
|
||||
"dependencies": {
|
||||
"@vercel/postgres": "0.7.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"kysely": "^0.24.2 || ^0.25.0 || ^0.26.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitejs/plugin-react": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz",
|
||||
|
@ -2222,6 +2278,18 @@
|
|||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/bufferutil": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz",
|
||||
"integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.14.2"
|
||||
}
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
|
@ -3845,6 +3913,14 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/kysely": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/kysely/-/kysely-0.27.2.tgz",
|
||||
"integrity": "sha512-DmRvEfiR/NLpgsTbSxma2ldekhsdcd65+MNiKXyd/qj7w7X5e3cLkXxcj+MypsRDjPhHQ/CD5u3Eq1sBYzX0bw==",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lilconfig": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz",
|
||||
|
@ -5364,6 +5440,34 @@
|
|||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
|
||||
"integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw=="
|
||||
},
|
||||
"node_modules/pg-int8": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
|
||||
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pg-protocol": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz",
|
||||
"integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q=="
|
||||
},
|
||||
"node_modules/pg-types": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
|
||||
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
|
||||
"dependencies": {
|
||||
"pg-int8": "1.0.1",
|
||||
"postgres-array": "~2.0.0",
|
||||
"postgres-bytea": "~1.0.0",
|
||||
"postgres-date": "~1.0.4",
|
||||
"postgres-interval": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
|
@ -5585,6 +5689,41 @@
|
|||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
|
||||
},
|
||||
"node_modules/postgres-array": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
|
||||
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/postgres-bytea": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
|
||||
"integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/postgres-date": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
|
||||
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/postgres-interval": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
|
||||
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
|
||||
"dependencies": {
|
||||
"xtend": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prebuild-install": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
|
||||
|
@ -7319,6 +7458,11 @@
|
|||
"node": ">=14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
||||
},
|
||||
"node_modules/unherit": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/unherit/-/unherit-3.0.1.tgz",
|
||||
|
@ -7473,6 +7617,18 @@
|
|||
"browserslist": ">= 4.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utf-8-validate": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.3.tgz",
|
||||
"integrity": "sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.14.2"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
@ -8037,6 +8193,34 @@
|
|||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.14.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
|
||||
"integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
|
|
|
@ -21,9 +21,11 @@
|
|||
"@types/react": "^18.2.47",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@vercel/blob": "^0.19.0",
|
||||
"@vercel/postgres-kysely": "^0.7.1",
|
||||
"astro": "^4.1.2",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.0",
|
||||
"kysely": "^0.27.2",
|
||||
"lucide-react": "^0.309.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
|
|
@ -1,15 +1,70 @@
|
|||
export const prerender = false
|
||||
|
||||
import { put } from "@vercel/blob"
|
||||
import type { Generated } from "kysely"
|
||||
import type { APIRoute } from "astro"
|
||||
import { createKysely } from "@vercel/postgres-kysely"
|
||||
|
||||
interface ContentTable {
|
||||
id: Generated<number>
|
||||
blob_url: string
|
||||
loc: string
|
||||
description: string
|
||||
}
|
||||
|
||||
interface Database {
|
||||
contents: ContentTable
|
||||
}
|
||||
|
||||
export const POST: APIRoute = async ({ request }) => {
|
||||
const data = await request.formData()
|
||||
|
||||
console.log(data)
|
||||
const image = data.get("selected-photo") as File
|
||||
const description = data.get("description")
|
||||
const geolocation = data.get("geolocation")
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
message: "This was a POST!"
|
||||
console.log(image, description, geolocation)
|
||||
|
||||
if (!image || !geolocation) {
|
||||
return new Response(null, {
|
||||
status: 400,
|
||||
statusText: "Image and geolocation are required fields"
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const pos = geolocation.toString().split(",")
|
||||
|
||||
if (pos.length !== 2) {
|
||||
return new Response(null, {
|
||||
status: 400,
|
||||
statusText: "Geolocation not correctly formatted"
|
||||
})
|
||||
}
|
||||
|
||||
const blob = await put(image.name, image, { access: "public", token: import.meta.env.BLOB_READ_WRITE_TOKEN })
|
||||
|
||||
const db = createKysely<Database>({ connectionString: import.meta.env.POSTGRES_URL })
|
||||
|
||||
const res = await db
|
||||
.insertInto("contents")
|
||||
.values({
|
||||
blob_url: blob.url,
|
||||
description: description?.toString() ?? "",
|
||||
loc: `SRID=4326;POINT(${pos[0]} ${pos[1]})`
|
||||
})
|
||||
.returning("blob_url")
|
||||
.executeTakeFirst()
|
||||
|
||||
if (res?.blob_url) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
message: "Succesfully added content"
|
||||
})
|
||||
)
|
||||
} else {
|
||||
return new Response(null, {
|
||||
status: 500,
|
||||
statusText: "Error while saving data"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ import { Textarea } from '@/components/ui/textarea';
|
|||
>
|
||||
</p>
|
||||
</div>
|
||||
<input name="geolocation" id="geolocation-input" hidden />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
@ -81,7 +82,10 @@ import { Textarea } from '@/components/ui/textarea';
|
|||
3. Fotoğraf Açıklaması
|
||||
</h2>
|
||||
<div class="grid w-full max-w-sm items-center gap-1.5 mt-4">
|
||||
<Textarea placeholder="Açıklamanızı buraya yazınız." name="desc" />
|
||||
<Textarea
|
||||
placeholder="Açıklamanızı buraya yazınız."
|
||||
name="description"
|
||||
/>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Bir açıklama girin, yüklediğiniz içeriğin üzerine bu metin
|
||||
görünecek.
|
||||
|
|
|
@ -43,6 +43,8 @@ L.Control.GoToCurrentLocation = L.Control.extend({
|
|||
|
||||
locationButton.classList.add('custom-map-control-button');
|
||||
|
||||
locationButton.name = 'select-location-button'
|
||||
|
||||
locationButton.addEventListener('click', () => {
|
||||
map.setView(currentLocationMarker.getLatLng(), 18);
|
||||
});
|
||||
|
|
|
@ -36,10 +36,14 @@ L.Control.GoToCurrentLocation = L.Control.extend({
|
|||
|
||||
locationButton.classList.add('custom-map-control-button');
|
||||
|
||||
locationButton.addEventListener('click', (e) => {
|
||||
map.setView(currentLocationMarker.getLatLng(), 18);
|
||||
e.stopPropagation()
|
||||
});
|
||||
locationButton.type = 'button'
|
||||
|
||||
locationButton.addEventListener('click', (ev) => {
|
||||
if (currentLocationMarker) {
|
||||
map.setView(currentLocationMarker.getLatLng(), 12);
|
||||
}
|
||||
L.DomEvent.stopPropagation(ev)
|
||||
})
|
||||
|
||||
return locationButton;
|
||||
},
|
||||
|
@ -115,5 +119,6 @@ map.on('click', (e) => {
|
|||
|
||||
const pos = targetLocationMarker.getLatLng()
|
||||
document.getElementById('coordinates').innerText = `${pos.lat}. Enlem, ${pos.lng}. Boylam`
|
||||
document.getElementById('geolocation-input').value = `${pos.lat},${pos.lng}`
|
||||
document.getElementById('location-selected-confirmation').innerText = "Konum seçildi, bir sonraki adıma geçebilirsiniz."
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue
Block a user