Skip to content

Commit d55c154

Browse files
committed
feat: create a new meal and save it to the db
1 parent 528dd47 commit d55c154

File tree

8 files changed

+86
-4
lines changed

8 files changed

+86
-4
lines changed

app/meals/share/page.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import ImagePicker from '@/components/meals/image-picker';
2-
2+
import { shareMeal } from '@/lib/actions';
33
import classes from './page.module.css';
44

55
export default function ShareMealPage() {
@@ -12,7 +12,7 @@ export default function ShareMealPage() {
1212
<p>Or any other meal you feel needs sharing!</p>
1313
</header>
1414
<main className={classes.main}>
15-
<form className={classes.form}>
15+
<form className={classes.form} action={shareMeal}>
1616
<div className={classes.row}>
1717
<p>
1818
<label htmlFor='name'>Your name</label>
@@ -40,7 +40,7 @@ export default function ShareMealPage() {
4040
required
4141
></textarea>
4242
</p>
43-
<ImagePicker name='image' label='image' />
43+
<ImagePicker name='image' label='Your image' />
4444
<p className={classes.actions}>
4545
<button type='submit'>Share Meal</button>
4646
</p>

lib/actions.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use server';
2+
import { redirect } from 'next/navigation';
3+
4+
import { saveMeal } from '@/lib/meals';
5+
6+
export const shareMeal = async (formData) => {
7+
const meal = {
8+
title: formData.get('title'),
9+
summary: formData.get('summary'),
10+
instructions: formData.get('instructions'),
11+
image: formData.get('image'),
12+
creator: formData.get('name'),
13+
creator_email: formData.get('email'),
14+
};
15+
16+
await saveMeal(meal);
17+
redirect('/meals');
18+
};

lib/meals.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
import fs from 'node:fs';
2+
13
import sql from 'better-sqlite3';
4+
import slugify from 'slugify';
5+
import xss from 'xss';
26

37
const db = sql('meals.db');
48

@@ -12,3 +16,38 @@ export const getMeals = async () => {
1216
export const getMeal = (slug) => {
1317
return db.prepare('SELECT * FROM meals WHERE slug = ?').get(slug);
1418
};
19+
20+
export const saveMeal = async (meal) => {
21+
meal.slug = slugify(meal.title, { lower: true });
22+
meal.instructions = xss(meal.instructions);
23+
24+
const extension = meal.image.name.split('.').pop();
25+
const fileName = `${meal.slug}.${extension}`;
26+
27+
const stream = fs.createWriteStream(`public/images/${fileName}`);
28+
const bufferedImage = await meal.image.arrayBuffer();
29+
30+
stream.write(Buffer.from(bufferedImage), (error) => {
31+
if (error) {
32+
throw new Error('Saving image failed');
33+
}
34+
});
35+
36+
meal.image = `/images/${fileName}`;
37+
38+
db.prepare(
39+
`
40+
INSERT INTO meals
41+
(title, summary, instructions, creator, creator_email, image, slug)
42+
VALUES (
43+
@title,
44+
@summary,
45+
@instructions,
46+
@creator,
47+
@creator_email,
48+
@image,
49+
@slug
50+
)
51+
`
52+
).run(meal);
53+
};

meals.db

0 Bytes
Binary file not shown.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
"better-sqlite3": "^9.5.0",
1313
"next": "14.0.3",
1414
"react": "^18",
15-
"react-dom": "^18"
15+
"react-dom": "^18",
16+
"slugify": "^1.6.6",
17+
"xss": "^1.0.15"
1618
},
1719
"devDependencies": {
1820
"eslint": "^8",

public/images/fdasgd.png

315 KB
Loading

public/images/fdsf.png

258 KB
Loading

yarn.lock

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,11 @@ color-name@~1.1.4:
505505
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
506506
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
507507

508+
commander@^2.20.3:
509+
version "2.20.3"
510+
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
511+
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
512+
508513
509514
version "0.0.1"
510515
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -519,6 +524,11 @@ cross-spawn@^7.0.2:
519524
shebang-command "^2.0.0"
520525
which "^2.0.1"
521526

527+
528+
version "0.0.10"
529+
resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae"
530+
integrity sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==
531+
522532
damerau-levenshtein@^1.0.8:
523533
version "1.0.8"
524534
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
@@ -2120,6 +2130,11 @@ slash@^3.0.0:
21202130
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
21212131
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
21222132

2133+
slugify@^1.6.6:
2134+
version "1.6.6"
2135+
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.6.6.tgz#2d4ac0eacb47add6af9e04d3be79319cbcc7924b"
2136+
integrity sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==
2137+
21232138
source-map-js@^1.0.2:
21242139
version "1.2.0"
21252140
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
@@ -2437,6 +2452,14 @@ wrappy@1:
24372452
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
24382453
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
24392454

2455+
xss@^1.0.15:
2456+
version "1.0.15"
2457+
resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.15.tgz#96a0e13886f0661063028b410ed1b18670f4e59a"
2458+
integrity sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==
2459+
dependencies:
2460+
commander "^2.20.3"
2461+
cssfilter "0.0.10"
2462+
24402463
yallist@^4.0.0:
24412464
version "4.0.0"
24422465
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"

0 commit comments

Comments
 (0)