mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 18:52:06 +00:00
feat: implement user follow system
This commit is contained in:
14
src/prisma/migrations/20231112221155_/migration.sql
Normal file
14
src/prisma/migrations/20231112221155_/migration.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "UserFollow" (
|
||||
"followerId" TEXT NOT NULL,
|
||||
"followingId" TEXT NOT NULL,
|
||||
"followedAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "UserFollow_pkey" PRIMARY KEY ("followerId","followingId")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "UserFollow" ADD CONSTRAINT "UserFollow_followerId_fkey" FOREIGN KEY ("followerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "UserFollow" ADD CONSTRAINT "UserFollow_followingId_fkey" FOREIGN KEY ("followingId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -44,6 +44,18 @@ model User {
|
||||
beerStyleLikes BeerStyleLike[]
|
||||
beerStyleComments BeerStyleComment[]
|
||||
userAvatar UserAvatar?
|
||||
followedBy UserFollow[] @relation("following")
|
||||
following UserFollow[] @relation("follower")
|
||||
}
|
||||
|
||||
model UserFollow {
|
||||
follower User @relation("follower", fields: [followerId], references: [id])
|
||||
followerId String
|
||||
following User @relation("following", fields: [followingId], references: [id])
|
||||
followingId String
|
||||
followedAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
|
||||
@@id([followerId, followingId])
|
||||
}
|
||||
|
||||
model UserAvatar {
|
||||
|
||||
54
src/prisma/seed/create/createNewUserFollows.ts
Normal file
54
src/prisma/seed/create/createNewUserFollows.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { User } from '@prisma/client';
|
||||
|
||||
import DBClient from '../../DBClient';
|
||||
|
||||
interface CreateNewUserFollowsArgs {
|
||||
joinData: { users: User[] };
|
||||
}
|
||||
|
||||
interface UserFollowData {
|
||||
followerId: string;
|
||||
followingId: string;
|
||||
followedAt: Date;
|
||||
}
|
||||
|
||||
const createNewUserFollows = async ({
|
||||
joinData: { users },
|
||||
}: CreateNewUserFollowsArgs) => {
|
||||
const userFollows: UserFollowData[] = [];
|
||||
|
||||
users.forEach((user) => {
|
||||
// Get 20 random users to follow.
|
||||
const randomUsers = users
|
||||
.filter((randomUser) => randomUser.id !== user.id)
|
||||
.sort(() => Math.random() - Math.random())
|
||||
.slice(0, 20);
|
||||
|
||||
// Get the user to follow the random users, and the random users to follow the user.
|
||||
const data = randomUsers.flatMap((randomUser) => [
|
||||
{
|
||||
followerId: user.id,
|
||||
followingId: randomUser.id,
|
||||
followedAt: faker.date.between({ from: user.createdAt, to: new Date() }),
|
||||
},
|
||||
{
|
||||
followerId: randomUser.id,
|
||||
followingId: user.id,
|
||||
followedAt: faker.date.between({ from: randomUser.createdAt, to: new Date() }),
|
||||
},
|
||||
]);
|
||||
|
||||
userFollows.push(...data);
|
||||
});
|
||||
|
||||
await DBClient.instance.userFollow.createMany({
|
||||
data: userFollows,
|
||||
skipDuplicates: true,
|
||||
});
|
||||
|
||||
return DBClient.instance.userFollow.findMany();
|
||||
};
|
||||
|
||||
export default createNewUserFollows;
|
||||
@@ -18,6 +18,7 @@ interface UserData {
|
||||
hash: string;
|
||||
accountIsVerified: boolean;
|
||||
role: 'USER' | 'ADMIN';
|
||||
bio: string;
|
||||
}
|
||||
|
||||
const createNewUsers = async ({ numberOfUsers }: CreateNewUsersArgs) => {
|
||||
@@ -54,6 +55,7 @@ const createNewUsers = async ({ numberOfUsers }: CreateNewUsersArgs) => {
|
||||
|
||||
const dateOfBirth = faker.date.birthdate({ mode: 'age', min: 19 });
|
||||
const createdAt = faker.date.past({ years: 4 });
|
||||
const bio = faker.lorem.paragraphs(3).replace(/\n/g, ' ');
|
||||
|
||||
const user: UserData = {
|
||||
firstName,
|
||||
@@ -63,6 +65,7 @@ const createNewUsers = async ({ numberOfUsers }: CreateNewUsersArgs) => {
|
||||
dateOfBirth,
|
||||
createdAt,
|
||||
hash,
|
||||
bio,
|
||||
accountIsVerified: true,
|
||||
role: 'USER',
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@ import createAdminUser from './create/createAdminUser';
|
||||
import createNewBeerStyleComments from './create/createNewBeerStyleComments';
|
||||
import createNewBeerStyleLikes from './create/createNewBeerStyleLikes';
|
||||
import createNewUserAvatars from './create/createNewUserAvatars';
|
||||
import createNewUserFollows from './create/createNewUserFollows';
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
@@ -37,6 +38,9 @@ import createNewUserAvatars from './create/createNewUserAvatars';
|
||||
const userAvatars = await createNewUserAvatars({ joinData: { users } });
|
||||
logger.info('User avatars created successfully.');
|
||||
|
||||
const userFollows = await createNewUserFollows({ joinData: { users } });
|
||||
logger.info('User follows created successfully.');
|
||||
|
||||
const locations = await createNewLocations({
|
||||
numberOfLocations: 500,
|
||||
joinData: { users },
|
||||
@@ -108,6 +112,7 @@ import createNewUserAvatars from './create/createNewUserAvatars';
|
||||
logger.info({
|
||||
numberOfUsers: users.length,
|
||||
numberOfUserAvatars: userAvatars.length,
|
||||
numberOfUserFollows: userFollows.length,
|
||||
numberOfBreweryPosts: breweryPosts.length,
|
||||
numberOfBeerPosts: beerPosts.length,
|
||||
numberOfBeerStyles: beerStyles.length,
|
||||
|
||||
Reference in New Issue
Block a user