File size: 3,366 Bytes
3ec134e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// backend/src/posts/service.ts
import { prisma } from '../utils/prisma';
import { Category, Prisma } from '@prisma/client';

export async function listPosts(params: {
  category?: Category;
  keyword?: string;
  emojiTags?: string[];
  limit?: number;
  offset?: number;
}) {
  const { category, keyword, emojiTags, limit = 20, offset = 0 } = params;
  const where: Prisma.PostWhereInput = {
    visibility: 'public',
    ...(category ? { category } : {}),
    ...(keyword ? {
      OR: [
        { title: { contains: keyword, mode: 'insensitive' } },
        { subtitle: { contains: keyword, mode: 'insensitive' } },
        { contentMd: { contains: keyword, mode: 'insensitive' } },
        { description: { contains: keyword, mode: 'insensitive' } },
      ]
    } : {}),
    ...(emojiTags?.length ? {
      tags: { some: { tag: { emoji: { in: emojiTags } } } }
    } : {}),
  };
  const [items, total] = await Promise.all([
    prisma.post.findMany({
      where,
      orderBy: { createdAt: 'desc' },
      include: { tags: { include: { tag: true } } },
      skip: offset, take: limit,
    }),
    prisma.post.count({ where }),
  ]);
  return { items, total };
}

export async function getPostBySlug(slug: string) {
  return prisma.post.findUnique({
    where: { slug },
    include: { tags: { include: { tag: true } } },
  });
}

export async function connectTagsByEmojis(postId: string, emojis: string[]) {
  if (!emojis?.length) {
    await prisma.tagOnPost.deleteMany({ where: { postId } });
    return;
  }
  const tagRecords = await prisma.tag.findMany({ where: { emoji: { in: emojis } } });
  await prisma.tagOnPost.deleteMany({ where: { postId } });
  await prisma.tagOnPost.createMany({
    data: tagRecords.map(t => ({ postId, tagId: t.id })),
    skipDuplicates: true,
  });
}

export async function createPost(data: {
  slug: string;
  title: string;
  subtitle?: string;
  category: Category;
  contentMd: string;
  coverUrl?: string;
  visibility?: string;
  language?: string;
  description?: string;
  emojis?: string[];
}) {
  const post = await prisma.post.create({
    data: {
      slug: data.slug,
      title: data.title,
      subtitle: data.subtitle,
      category: data.category,
      contentMd: data.contentMd,
      coverUrl: data.coverUrl,
      visibility: data.visibility ?? 'public',
      language: data.language,
      description: data.description,
    },
  });
  await connectTagsByEmojis(post.id, data.emojis || []);
  return await getPostBySlug(post.slug);
}

export async function updatePostBySlug(slug: string, data: {
  slug?: string;
  title?: string;
  subtitle?: string;
  category?: Category;
  contentMd?: string;
  coverUrl?: string;
  visibility?: string;
  language?: string;
  description?: string;
  emojis?: string[];
}) {
  const post = await prisma.post.update({
    where: { slug },
    data: {
      slug: data.slug,
      title: data.title,
      subtitle: data.subtitle,
      category: data.category,
      contentMd: data.contentMd,
      coverUrl: data.coverUrl,
      visibility: data.visibility,
      language: data.language,
      description: data.description,
    },
  });
  if (data.emojis) await connectTagsByEmojis(post.id, data.emojis);
  return await getPostBySlug(post.slug);
}

export async function deletePostBySlug(slug: string) {
  await prisma.post.delete({ where: { slug } });
}