From 9129e48ed2ec3f63d9ffa00e1c7fe896291ff8ba Mon Sep 17 00:00:00 2001 From: onkar69483 Date: Sat, 6 Sep 2025 10:26:34 +0530 Subject: [PATCH] rooms version 1 added Database Schema Changes (schema.prisma): Added a new Room model with: Unique 6-digit code for room identification One-to-many relationship with Pastes Created at timestamp Updated Paste model to include: Optional relationship to Room Room ID foreign key Room Page Implementation (+page.svelte): Created a dynamic route with room code parameter Implemented features: Room header showing room code with copy button Paste creation form with: Title input Language selector Code editor with preview File drag-and-drop support Syntax highlighting using Prism.js Real-time paste list updates using SvelteKit's reactivity Form handling improvements: Added enctype="multipart/form-data" for file uploads Reactive form submission with automatic UI updates Form clearing after successful submission Server-Side Logic (+page.server.js): Load function to fetch room data: Retrieves room by code with related pastes Orders pastes by creation date Includes error handling for non-existent rooms Form actions: createPaste: Handles paste creation in rooms Validates room existence Creates paste with room association UI/UX Features: Responsive design for all screen sizes Gradient backgrounds and card-based layout Interactive elements: Copy buttons for room code and paste content File drag-and-drop zone with visual feedback Code editor/preview toggle Syntax highlighting for multiple languages Toast notifications for user feedback Loading states and error handling Data Flow Improvements: Reactive bindings for real-time updates SvelteKit's form enhancement for smooth submissions Automatic UI updates after paste creation Optimized data invalidation and reloading Latest Fixes: Resolved form submission issues: Added proper enctype for file uploads Fixed form clearing after submission Improved data reactivity: Added reactive binding for room data Implemented proper data invalidation Fixed refresh issues with paste list updates The feature now provides: Private rooms identified by 6-digit codes Real-time paste sharing within rooms Rich code editing experience Immediate UI updates without page refreshes Robust error handling and user feedback The room feature is now fully functional, allowing users to: Create or join rooms using codes Share code snippets in real-time View and interact with shared pastes Copy and view detailed paste information --- prisma/schema.prisma | 21 +- src/lib/dataStore.js | 13 +- src/routes/+page.svelte | 539 ++++++++++++++---------- src/routes/+page.svelte.fix | 1 + src/routes/components/Header.svelte | 19 +- src/routes/components/Hero.svelte | 8 +- src/routes/rooms/+page.js | 28 ++ src/routes/rooms/+page.svelte | 75 ++++ src/routes/rooms/+server.js | 60 +++ src/routes/rooms/[code]/+page.js | 14 + src/routes/rooms/[code]/+page.server.js | 97 +++++ src/routes/rooms/[code]/+page.svelte | 316 ++++++++++++++ 12 files changed, 957 insertions(+), 234 deletions(-) create mode 100644 src/routes/+page.svelte.fix create mode 100644 src/routes/rooms/+page.js create mode 100644 src/routes/rooms/+page.svelte create mode 100644 src/routes/rooms/+server.js create mode 100644 src/routes/rooms/[code]/+page.js create mode 100644 src/routes/rooms/[code]/+page.server.js create mode 100644 src/routes/rooms/[code]/+page.svelte diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2ee01c9..e205160 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -19,12 +19,21 @@ model Snippet { createdAt DateTime @default(now()) } +model Room { + id String @id @default(auto()) @map("_id") @db.ObjectId + code String @unique + createdAt DateTime @default(now()) + pastes Paste[] +} + model Paste { - id String @id @default(auto()) @map("_id") @db.ObjectId - text String - title String - password String? + id String @id @default(auto()) @map("_id") @db.ObjectId + text String + title String + password String? paste_expiration Int? - encrypted Int? - createdAt DateTime @default(now()) + encrypted Int? + createdAt DateTime @default(now()) + roomId String? @db.ObjectId + room Room? @relation(fields: [roomId], references: [id]) } \ No newline at end of file diff --git a/src/lib/dataStore.js b/src/lib/dataStore.js index 48fd402..8ef55d5 100644 --- a/src/lib/dataStore.js +++ b/src/lib/dataStore.js @@ -6,7 +6,17 @@ const prisma = new PrismaClient(); // Function to insert a new paste export async function insertPaste(data) { - const { text, title, password, paste_expiration, encrypted } = data; + const { text, title, password, paste_expiration, encrypted, roomCode } = data; + + let roomId = undefined; + if (roomCode) { + const room = await prisma.room.findUnique({ + where: { code: roomCode } + }); + if (room) { + roomId = room.id; + } + } // Insert the new paste into MongoDB const newPaste = await prisma.paste.create({ @@ -16,6 +26,7 @@ export async function insertPaste(data) { password, paste_expiration, encrypted, + roomId }, }); diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index d00c8e2..74c25fb 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -9,17 +9,57 @@ import "prismjs/components/prism-python"; import "prismjs/components/prism-java"; import toast, { Toaster } from "svelte-french-toast"; - import Hero from "./components/Hero.svelte"; import { fade, slide } from "svelte/transition"; import { quintOut } from "svelte/easing"; import { enhance } from "$app/forms"; + import { goto } from '$app/navigation'; + + let view = 'choose'; // 'choose', 'public', 'room' + let roomCode = ''; + let error = ''; + let loading = false; + + // Function to create a new room + async function createRoom() { + loading = true; + try { + const response = await fetch('/rooms', { + method: 'POST' + }); + const data = await response.json(); + if (response.ok) { + goto(`/rooms/${data.room.code}`); + } else { + error = data.error; + toast.error(data.error); + } + } catch (err) { + error = 'Failed to create room'; + toast.error('Failed to create room'); + } finally { + loading = false; + } + } + + // Function to join a room + async function joinRoom() { + if (!roomCode) { + toast.error('Please enter a room code'); + return; + } + if (roomCode.length !== 6) { + toast.error('Invalid room code format'); + return; + } + goto(`/rooms/${roomCode}`); + } let selectedLanguage = "markup"; let isDragging = false; let showSuccessToast = false; let toastMessage = ""; - let toastType = "success"; // 'success' or 'error' - let currentTab = "editor"; // 'editor' or 'preview' + let toastType = "success"; + let currentTab = "editor"; let createdPasteUrl = ""; const languageOptions = [ @@ -34,20 +74,18 @@ function formatExpirationTime(expirationTimestamp: number | null): string { if (expirationTimestamp === null) return "Never"; - const now = Date.now(); const secondsRemaining = Math.floor((expirationTimestamp - now) / 1000); - if (secondsRemaining <= 0) return "Expired"; if (secondsRemaining < 60) return `${secondsRemaining}s`; if (secondsRemaining < 3600) return `${Math.floor(secondsRemaining / 60)}m`; - if (secondsRemaining < 86400) - return `${Math.floor(secondsRemaining / 3600)}h`; + if (secondsRemaining < 86400) return `${Math.floor(secondsRemaining / 3600)}h`; return `${Math.floor(secondsRemaining / 86400)}d`; } - + function showToast(message: string, type: 'success' | 'error' = 'success') { toastMessage = message; + toast[type](message); toastType = type; showSuccessToast = true; setTimeout(() => { @@ -210,239 +248,304 @@ } - - -{#if showSuccessToast} -
- - {#if toastType === 'success'} - ✓ - {:else} - ✕ - {/if} - -

{toastMessage}

-
-{/if} - -
-
- -
-

- 📋 Create a New Paste -

- -
- -
- - -
- - -
- - -
- - -
+
+

Welcome to CodeDrop

+

Choose how you want to share your code

+ +
+ +
- - - {#if isDragging} -
+
+ 🔒 +
+

Create Private Room

+

+ Get a private room with a unique code for secure collaboration +

+ {#if loading} +
Creating room...
{/if}
- -
-
- + +
+
+ 🤝 +
+

Join Room

+

+ Enter a room code to collaborate +

+
+
- -
- -
-
- -
- - + +
view = 'public'} + > +
+ 🌐 +
+

Public Paste

+

+ Create or view public pastes accessible to everyone +

+
- -
- - -
- + {#if error} +
{error}
+ {/if}
+
+{:else if view === 'public'} +
+ + +
+ + +
+ +
+

+ 📋 Create a New Paste +

+ +
+ +
+ + +
- -
-

- 📚 Recent Pastes -

+ +
+ + +
- {#if data.pastes && data.pastes.length > 0} -
- {#each data.pastes as paste} +
-
-

{paste.title}

- - ⏳ {formatExpirationTime(paste.paste_expiration)} - -
+ + + {#if isDragging} +
+ {/if} +
-

- {paste.text} -

- -
- - 👁️ View - + +
+
+ - -
+
+ +
+ +
+
+
+ + +
+ + +
+ + +
+ +
- {/each} +
- {:else} -
-
📭
-

No pastes found. Create your first paste above!

+ + +
+

+ 📚 Recent Pastes +

+ + {#if data.pastes && data.pastes.length > 0} +
+ {#each data.pastes as paste} +
+
+

{paste.title}

+ + ⏳ {formatExpirationTime(paste.paste_expiration)} + +
+ +

+ {paste.text} +

+ +
+ + 👁️ View + + + +
+
+ {/each} +
+ {:else} +
+
📭
+

No pastes found. Create your first paste above!

+
+ {/if}
- {/if} +
-
+{/if} \ No newline at end of file diff --git a/src/routes/+page.svelte.fix b/src/routes/+page.svelte.fix new file mode 100644 index 0000000..4fdf8be --- /dev/null +++ b/src/routes/+page.svelte.fix @@ -0,0 +1 @@ +# Temporary fix file diff --git a/src/routes/components/Header.svelte b/src/routes/components/Header.svelte index d30bea2..963510c 100644 --- a/src/routes/components/Header.svelte +++ b/src/routes/components/Header.svelte @@ -25,7 +25,10 @@ } function handleNavClick(event) { - const targetId = event.target.getAttribute('href').split('#')[1]; + const href = event.target.getAttribute('href'); + if (!href || !href.includes('#')) return; + + const targetId = href.split('#')[1]; const element = document.getElementById(targetId); if (element) { @@ -65,8 +68,11 @@