Evently
uploadthingShadcnTypeScriptZodReactStripeTailwindCSSNext.jsNode.jsreactjs
Thursday, February 1, 2024
Evently
Built on Next.js 14, the events application stands as a comprehensive, full-stack platform for managing events. It serves as a hub, spotlighting diverse events taking place globally. Featuring seamless payment processing through Stripe, you have the capability to purchase tickets for any event or even initiate and manage your own events.
Features
- Authentication (CRUD) with Clerk: User management through Clerk, ensuring secure and efficient authentication.
- Events (CRUD): Comprehensive functionality for creating, reading, updating, and deleting events, giving users full control over event management.
- Create Events: Users can effortlessly generate new events, providing essential details such as title, date, location, and any additional information.
- Read Events: Seamless access to a detailed view of all events, allowing users to explore event specifics, including descriptions, schedules, and related information.
- Update Events: Empowering users to modify event details dynamically, ensuring that event information remains accurate and up-to-date.
- Delete Events: A straightforward process for removing events from the system, giving administrators the ability to manage and curate the platform effectively.
- Related Events: Smartly connects events that are related and displaying on the event details page, making it more engaging for users
- Organized Events: Efficient organization of events, ensuring a structured and user-friendly display for the audience, i.e., showing events created by the user on the user profile
- Search & Filter: Empowering users with a robust search and filter system, enabling them to easily find the events that match their preferences.
- New Category: Dynamic categorization allows for the seamless addition of new event categories, keeping your platform adaptable.
- Checkout and Pay with Stripe: Smooth and secure payment transactions using Stripe, enhancing user experience during the checkout process.
- Event Orders: Comprehensive order management system, providing a clear overview of all event-related transactions.
- Search Orders: Quick and efficient search functionality for orders, facilitating easy tracking and management.
@tailwind base; @tailwind components; @tailwind utilities; @layer base { :root { --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; --card: 0 0% 100%; --card-foreground: 222.2 84% 4.9%; --popover: 0 0% 100%; --popover-foreground: 222.2 84% 4.9%; --primary: 222.2 47.4% 11.2%; --primary-foreground: 210 40% 98%; --secondary: 210 40% 96.1%; --secondary-foreground: 222.2 47.4% 11.2%; --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; --accent: 210 40% 96.1%; --accent-foreground: 222.2 47.4% 11.2%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 210 40% 98%; --border: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%; --ring: 222.2 84% 4.9%; --radius: 0.5rem; } .dark { --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; --card: 222.2 84% 4.9%; --card-foreground: 210 40% 98%; --popover: 222.2 84% 4.9%; --popover-foreground: 210 40% 98%; --primary: 210 40% 98%; --primary-foreground: 222.2 47.4% 11.2%; --secondary: 217.2 32.6% 17.5%; --secondary-foreground: 210 40% 98%; --muted: 217.2 32.6% 17.5%; --muted-foreground: 215 20.2% 65.1%; --accent: 217.2 32.6% 17.5%; --accent-foreground: 210 40% 98%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 210 40% 98%; --border: 217.2 32.6% 17.5%; --input: 217.2 32.6% 17.5%; --ring: 212.7 26.8% 83.9%; } } * { list-style: none; padding: 0; margin: 0; scroll-behavior: smooth; } body { font-family: var(--font-poppins) } .filter-grey { filter: brightness(0) saturate(100%) invert(47%) sepia(0%) saturate(217%) hue-rotate(32deg) brightness(98%) contrast(92%); }
/* ========================================== CLERK STYLES */ .cl-logoImage { height: 38px; } .cl-userButtonBox { flex-direction: row-reverse; } .cl-userButtonOuterIdentifier { font-size: 16px; } .cl-userButtonPopoverCard { right: 4px !important; } .cl-formButtonPrimary:hover, .cl-formButtonPrimary:focus, .cl-formButtonPrimary:active { background-color: #705CF7 } /* ========================================== REACT-DATEPICKER STYLES */ .datePicker { width: 100%; } .react-datepicker__input-container input { background-color: transparent; width: 100%; outline: none; margin-left: 16px; } .react-datepicker__day--selected { background-color: #624cf5 !important; color: #ffffff !important; border-radius: 4px; } .react-datepicker__time-list-item--selected { background-color: #624cf5 !important; }
'use server' import { revalidatePath } from 'next/cache' import { connectToDatabase } from '@/lib/database' import User from '@/lib/database/models/user.model' import Order from '@/lib/database/models/order.model' import Event from '@/lib/database/models/event.model' import { handleError } from '@/lib/utils' import { CreateUserParams, UpdateUserParams } from '@/types' export async function createUser(user: CreateUserParams) { try { await connectToDatabase() const newUser = await User.create(user) return JSON.parse(JSON.stringify(newUser)) } catch (error) { handleError(error) } } export async function getUserById(userId: string) { try { await connectToDatabase() const user = await User.findById(userId) if (!user) throw new Error('User not found') return JSON.parse(JSON.stringify(user)) } catch (error) { handleError(error) } }
export async function updateUser(clerkId: string, user: UpdateUserParams) { try { await connectToDatabase() const updatedUser = await User.findOneAndUpdate({ clerkId }, user, { new: true }) if (!updatedUser) throw new Error('User update failed') return JSON.parse(JSON.stringify(updatedUser)) } catch (error) { handleError(error) } } export async function deleteUser(clerkId: string) { try { await connectToDatabase() // Find user to delete const userToDelete = await User.findOne({ clerkId }) if (!userToDelete) { throw new Error('User not found') } // Unlink relationships await Promise.all([ // Update the 'events' collection to remove references to the user Event.updateMany( { _id: { $in: userToDelete.events } }, { $pull: { organizer: userToDelete._id } } ), // Update the 'orders' collection to remove references to the user Order.updateMany({ _id: { $in: userToDelete.orders } }, { $unset: { buyer: 1 } }), ]) // Delete user const deletedUser = await User.findByIdAndDelete(userToDelete._id) revalidatePath('/') return deletedUser ? JSON.parse(JSON.stringify(deletedUser)) : null } catch (error) { handleError(error) } }