Skip to content
Merged
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
8 changes: 6 additions & 2 deletions components.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
3 changes: 0 additions & 3 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
serverActions: true,
},
typescript: {
ignoreBuildErrors: true,
}
Expand Down
2,200 changes: 1,856 additions & 344 deletions package-lock.json

Large diffs are not rendered by default.

29 changes: 25 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,33 @@
"@auth/prisma-adapter": "^2.7.4",
"@hookform/resolvers": "^3.9.1",
"@next-auth/prisma-adapter": "^1.0.7",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-hover-card": "^1.1.6",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-toast": "^1.2.2",
"@tanstack/react-query": "^5.70.0",
"@tiptap/extension-bold": "^2.11.5",
"@tiptap/extension-bullet-list": "^2.11.5",
"@tiptap/extension-heading": "^2.11.5",
"@tiptap/extension-highlight": "^2.11.5",
"@tiptap/extension-italic": "^2.11.5",
"@tiptap/extension-link": "^2.11.5",
"@tiptap/extension-list-item": "^2.11.5",
"@tiptap/extension-paragraph": "^2.11.5",
"@tiptap/extension-placeholder": "^2.11.5",
"@tiptap/extension-underline": "^2.11.5",
"@tiptap/pm": "^2.11.5",
"@tiptap/react": "^2.11.5",
"@tiptap/starter-kit": "^2.11.5",
"axios": "^1.7.9",
"bcryptjs": "^2.4.3",
"class-variance-authority": "^0.7.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"embla-carousel-react": "^8.5.2",
"lucide-react": "^0.400.0",
"next": "^14.2.4",
"next-auth": "^4.24.11",
Expand All @@ -32,12 +50,15 @@
"react": "^18",
"react-dom": "^18",
"react-hook-form": "^7.53.2",
"shadcn-ui": "^0.9.3",
"tailwind-merge": "^2.3.0",
"react-intersection-observer": "^9.16.0",
"shadcn-ui": "^0.9.4",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.23.8"
},
"devDependencies": {
"@shadcn/ui": "^0.0.4",
"@tailwindcss/typography": "^0.5.16",
"@types/bcrypt": "^5.0.2",
"@types/bcryptjs": "^2.4.6",
"@types/node": "^20",
Expand Down
20 changes: 17 additions & 3 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@
//Copyright (C) 2025 Charlie Ward GPL v3
//Full License @ https://github.com/Charlie-Ward/CastConnect/blob/main/LICENSE

// Setting up the generator so it knows what syntax to use
generator client {
provider = "prisma-client-js"
}

// Setting where the output should be sent to
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

// Creating the Account table
model Account {
id String @id @default(cuid())
id String @id @default(cuid()) //Making it so this is the primary key.
userId String
type String
provider String
Expand All @@ -25,11 +28,12 @@ model Account {
id_token String? @db.Text
session_state String?

user User @relation(fields: [userId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade) //This creates a link between a user and an account

@@unique([provider, providerAccountId])
}

// Creating the Session table
model Session {
id String @id @default(cuid())
sessionToken String @unique
Expand All @@ -38,6 +42,7 @@ model Session {
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}

// Creating the User table
model User {
id String @id @default(cuid())
name String?
Expand All @@ -60,6 +65,7 @@ model User {
verificationTokens VerificationToken[]
}

// Creating the VerificationToken table
model VerificationToken {
id String @id @default(cuid())
token String @unique
Expand All @@ -69,7 +75,7 @@ model VerificationToken {
updatedAt DateTime @updatedAt
}


// Creating the ActivateToken table
model ActivateToken {
id Int @id @default(autoincrement())
token String @unique
Expand All @@ -80,12 +86,14 @@ model ActivateToken {
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}

//Setting the different types of posts available
enum TypePost {
IMAGE
VIDEO
POST
}

// Creating the Post table
model Post {
id String @id @default(dbgenerated("concat('post_', replace(cast(gen_random_uuid() as text), '-', ''))")) @db.Text
content String?
Expand All @@ -103,6 +111,7 @@ model Post {
Share Share[]
}

// Creating the Image table
model Image {
id String @id @default(dbgenerated("concat('image_', replace(cast(gen_random_uuid() as text), '-', ''))")) @db.Text
url String
Expand All @@ -111,6 +120,7 @@ model Image {
Post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
}

// Creating the Video table
model Video {
id String @id @default(dbgenerated("concat('video_', replace(cast(gen_random_uuid() as text), '-', ''))")) @db.Text
url String
Expand All @@ -119,6 +129,7 @@ model Video {
Post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
}

// Creating the Comment table
model Comment {
id String @id @default(dbgenerated("concat('comment_', replace(cast(gen_random_uuid() as text), '-', ''))")) @db.Text
content String
Expand All @@ -133,6 +144,7 @@ model Comment {
like Like[]
}

// Creating the Like table
model Like {
id String @id @default(dbgenerated("concat('like_', replace(cast(gen_random_uuid() as text), '-', ''))")) @db.Text
createdAt DateTime @default(now())
Expand All @@ -144,6 +156,7 @@ model Like {
comment Comment? @relation(fields: [commentId], references: [id], onDelete: Cascade)
}

// Creating the Save table
model Save {
id String @id @default(dbgenerated("concat('save_', replace(cast(gen_random_uuid() as text), '-', ''))")) @db.Text
createdAt DateTime @default(now())
Expand All @@ -153,6 +166,7 @@ model Save {
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
}

// Creating the Share table
model Share {
id String @id @default(dbgenerated("concat('share_', replace(cast(gen_random_uuid() as text), '-', ''))")) @db.Text
postId String
Expand Down
Binary file modified public/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 2 additions & 5 deletions src/ZodSchema/UserSchema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { z } from 'zod';

//Creating the format for the sign up form
export const SignUpSchema = z.object({
username:z.string().min(3, {
message: "Username must be at least 3 characters"
Expand All @@ -17,11 +18,6 @@ export const SignUpSchema = z.object({
message:"Please enter a password"
}),
confirmpassword:z.string()
// .min(8, {message: "Password must be at least 8 characters"})
// .max(15, {message: "Password must not be more than 15 characters"})
// .regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,15}$/,
// 'Password must contain at least one lowercase letter, one uppercase letter, one digit, one special character (@$!%*?&) and be between 8 to 15 characters long.'
// )
.refine(value => !!value, {
message:"Please confirm your password"
}),
Expand All @@ -30,6 +26,7 @@ export const SignUpSchema = z.object({
path:["confirmpassword"]
})

//Creating the format for the sign in form
export const SignInSchema = z.object({
email:z.string().email().refine(value => !!value, {
message: "Email is mandatory and should be a valid email address"
Expand Down
3 changes: 3 additions & 0 deletions src/app/(User)/forgotpassword/ForgotPasswordForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import { Input } from "@/components/ui/input"
import { Card } from "@/components/ui/card"
import { useToast } from "@/hooks/use-toast"
import { useRouter } from 'next/navigation'

type Props = {}

Expand All @@ -42,6 +43,7 @@ const ForgotPasswordSchema = z.object({

const ForgotPasswordForm = (props: Props) => {
const { toast } = useToast()
const router = useRouter()
const form = useForm<z.infer<typeof ForgotPasswordSchema>>({
resolver: zodResolver(ForgotPasswordSchema),
})
Expand All @@ -57,6 +59,7 @@ const ForgotPasswordForm = (props: Props) => {
description: "Password changed"
})
console.log(response)
router.push('/signin')
} catch (error) {
console.log("Error", error)
toast({
Expand Down
108 changes: 68 additions & 40 deletions src/app/(User)/signin/SignInForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ type Props = {}
const SignInForm = (props: Props) => {
const { toast } = useToast()
const router = useRouter()
const {data: Session, status} = useSession() // Able to see the session details from next-auth

// use the SignInSchema for this form
const form = useForm<z.infer<typeof SignInSchema>>({
resolver: zodResolver(SignInSchema),
defaultValues: {
Expand All @@ -42,60 +45,85 @@ const SignInForm = (props: Props) => {
async function onSubmit(values: z.infer<typeof SignInSchema>) {
console.log(values)
try {
// Sends details to an internal signIn command that I later pick up at api/auth/[...nextauth]/*
const response = await signIn('credentials', {
email:values.email,
password:values.password
email: values.email,
password: values.password,
redirect: false // Prevent redirect on error
})
console.log(response)

if (response?.error) {
throw new Error(response.error)
}

toast({
description: "User Registered Successfully"
description: "User Log In Successful"
})
router.push('/')
} catch (error) {
console.log(error)
toast({
description: "Something went wrong"
})
if (error instanceof Error) {
toast({
description: error.message || "Something went wrong"
})
} else {
toast({
description: "Something went wrong"
})
}
}
}

return (
<div className='mt-4 max-w-[1280px] mx-auto'>
<Card className='p-5 max-w-[600px] mx-auto'>
<CardHeader className='text-2xl font-semibold text-center'>Sign In</CardHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className='space-y-8'>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email Address</FormLabel>
<FormControl>
<Input type='email' placeholder="Email Address" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Password</FormLabel>
<FormControl>
<Input type='password' placeholder="Password" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Sign In</Button>
</form>
</Form>
<p className='text-m text-center'>Don&apos;t have an account <Link href="/signup" className='text-decoration: underline text-blue-500'>Sign Up</Link></p>
</Card>
{status === 'unauthenticated' && (
<>
<Form {...form}>
{/* Creating the form */}
<form onSubmit={form.handleSubmit(onSubmit)} className='space-y-8'>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email Address</FormLabel>
<FormControl>
<Input type='email' placeholder="Email Address" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Password</FormLabel>
<FormControl>
<Input type='password' placeholder="Password" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Sign In</Button>
</form>
</Form>
<p className='text-m text-center'>Forgot your password? <Link href="/forgotpassword" className='text-decoration: underline text-blue-500'>Reset it</Link></p>
<p className='text-m text-center'>Don&apos;t have an account? <Link href="/signup" className='text-decoration: underline text-blue-500'>Sign Up</Link></p>
</>
)}
{status === "authenticated" && ( //If user is logged in
<div>
<p className='text-centre'>You are currently logged in to log in with another account.</p>
<p className='text-centre'>To continue please first logout.</p>
Comment on lines +121 to +122
Copy link

Copilot AI Mar 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Tailwind CSS class 'text-centre' is misspelled; it should be 'text-center'.

Suggested change
<p className='text-centre'>You are currently logged in to log in with another account.</p>
<p className='text-centre'>To continue please first logout.</p>
<p className='text-center'>You are currently logged in to log in with another account.</p>
<p className='text-center'>To continue please first logout.</p>

Copilot uses AI. Check for mistakes.
<p className='text-red-500 text-center cursor-pointer underline' onClick={() => signOut()}>Sign Out</p>
</div>
)}
</Card>
</div>
)
}
Expand Down
Loading