Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ It simulates a real-world development workflow with collaborative feature develo
S25-Full-Stack-Circle/
├── frontend/ # React + Vite + CSS Modules
├── backend/ # Express + Prisma + PostgreSQL
├── scripts/ # Utility scripts for setup and maintenance
└── README.md

````
Expand Down Expand Up @@ -89,6 +90,24 @@ npm run seed

---

### 🏷️ Category System

The app uses a category-based organization system for pins:

- Each pin can belong to one category
- Categories are displayed on the Explore page

#### Seeding Categories

To populate the database with initial categories:

```bash
cd backend
node scripts/seed-categories.js
```

---

## ⚙ Tech Stack

* **Frontend**: React + Vite + CSS Modules
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
Warnings:

- You are about to drop the column `tags` on the `Pin` table. All the data in the column will be lost.

*/
-- AlterTable
ALTER TABLE "Pin" DROP COLUMN "tags",
ADD COLUMN "tag" TEXT[],
ALTER COLUMN "showSimilarProduct" SET DEFAULT false;
25 changes: 19 additions & 6 deletions backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -24,47 +24,60 @@ model User {
password String
createdAt DateTime @default(now())

board Board? @relation("UserBoard")
//board Board? @relation("UserBoard")
comments Comment[]
pins Pin[] @relation("CreatedPins")
reactions Reaction[]
savedPins SavedPin[]
}

model Category {
id Int @id @default(autoincrement())
title String @unique
imageUrl String?
description String?
createdAt DateTime @default(now())

pins Pin[]
}

model Pin {
id Int @id @default(autoincrement())
title String
authorId String
createdAt DateTime @default(now())
description String?
imageUrl String
boardId Int?
//boardId Int?
altText String?
isAllowedtoComment Boolean @default(true)
link String?
showSimilarProduct Boolean @default(false)
categoryId Int?
category Category? @relation(fields: [categoryId], references: [id])
comments Comment[]
author User @relation("CreatedPins", fields: [authorId], references: [id])
// board Board? @relation(fields: [boardId], references: [id])
reactions Reaction[]
savedPin SavedPin[]
tags Tag[] @relation("PinTags")
tags Tag[] @relation("PinTags")//----1b
//tag String[] //---1a
}

model Tag {
model Tag { //----1c
id Int @id @default(autoincrement())
name String @unique
pins Pin[] @relation("PinTags")
}

/*
model Board {
id Int @id @default(autoincrement())
name String
userId String @unique
user User @relation("UserBoard", fields: [userId], references: [id])
// pins Pin[]
}

*/
model Comment {
id Int @id @default(autoincrement())
userId String
Expand Down
29 changes: 29 additions & 0 deletions backend/scripts/clean-categories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { PrismaClient } from "@prisma/client";
// script used to cleanup categories in the database
const prisma = new PrismaClient();

async function main() {
console.log("Cleaning up categories...");

// First, remove category references from pins
await prisma.pin.updateMany({
data: {
categoryId: null
}
});

// Then delete all categories
await prisma.category.deleteMany({});

console.log("Categories cleaned up successfully!");
}

main()
.catch(e => {
console.error("Error cleaning up categories:", e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
process.exit(0);
});
Empty file.
105 changes: 105 additions & 0 deletions backend/scripts/seed-categories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Script to seed initial categories into the database
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

const categories = [
{
title: "Art",
description:
"Paintings, drawings, sculptures and other beautiful creations",
imageUrl: "https://picsum.photos/300/150?random=2"
},
{
title: "Beauty",
description: "Makeup, skincare, hair and other beauty topics",
imageUrl: "https://picsum.photos/300/150?random=3"
},
{
title: "Design",
description: "Graphic design, interior design and other creative designs",
imageUrl: "https://picsum.photos/300/150?random=4"
},
{
title: "DIY and Crafts",
description: "Do it yourself projects and crafting ideas",
imageUrl: "https://picsum.photos/300/150?random=5"
},
{
title: "Food and Drink",
description: "Recipes, cooking tips, and food inspiration",
imageUrl: "https://picsum.photos/300/150?random=6"
},
{
title: "Home Decor",
description: "Ideas to decorate and style your home",
imageUrl: "https://picsum.photos/300/150?random=7"
},
{
title: "Men's Fashion",
description: "Clothing, accessories and style for men",
imageUrl: "https://picsum.photos/300/150?random=8"
},
{
title: "Women's Fashion",
description: "Clothing, accessories and style for women",
imageUrl: "https://picsum.photos/300/150?random=9"
},
{
title: "Travel",
description: "Destinations, travel tips and vacation inspiration",
imageUrl: "https://picsum.photos/300/150?random=10"
},
{
title: "Technology",
description: "Gadgets, software, and tech innovations",
imageUrl: "https://picsum.photos/300/150?random=11"
},
{
title: "Nature",
description: "Beautiful landscapes, plants, and animals",
imageUrl: "https://picsum.photos/300/150?random=12"
},
{
title: "Photography",
description: "Photography inspiration, tips and techniques",
imageUrl: "https://picsum.photos/300/150?random=13"
}
];

async function main() {
console.log("Starting to seed categories...");

for (const category of categories) {
// Check if category already exists to avoid duplicates
const existing = await prisma.category.findFirst({
where: {
title: {
equals: category.title,
mode: "insensitive"
}
}
});

if (!existing) {
const created = await prisma.category.create({
data: category
});
console.log(`Created category: ${created.title}`);
} else {
console.log(`Category "${category.title}" already exists, skipping`);
}
}

console.log("Category seeding completed!");
}

main()
.catch(e => {
console.error("Error seeding categories:", e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
process.exit(0);
});
Loading