{name}
35 |@{username}
36 |No threads found
21 | ) : ( 22 | <> 23 | {result.posts.map((post) => ( 24 |26 | Complete your profile now, to use Threds. 27 |
28 | 29 |35 | {link.label.split(/\s+/)[0]} 36 |
37 | 38 | ); 39 | })} 40 |{pageNumber}
44 | 51 |@{username}
36 |No Result
37 | ) : ( 38 | <> 39 | {result.users.map((person) => ( 40 |38 | 39 | {activity.author.name} 40 | {" "} 41 | replied to your thread 42 |
43 |No activity yet
50 | )} 51 |@{username}
42 |Edit
55 |{bio}
61 | 62 | 63 |No Result
41 | ) : ( 42 | <> 43 | {result.communities.map((community) => ( 44 |{link.label}
40 | 41 | ); 42 | })} 43 |Logout
57 |@{username}
35 |{bio}
39 | 40 |62 | {members.length}+ Users 63 |
64 | )} 65 |9 | Threads Clone with NEXT.JS! (ReactJS, NextJS, Typescript, Tailwind CSS, MongoDB, Redux,Clerk (Google Authentication), ShadCN) 10 |
11 |42 | No communities yet 43 |
44 | )} 45 |No users yet
66 | )} 67 |{tab.label}
45 | 46 | {/* length of threads */} 47 | {tab.label === "Threads" && ( 48 |49 | {userInfo.threads.length} 50 |
51 | )} 52 |{tab.label}
44 | 45 | {tab.label === "Threads" && ( 46 |47 | {communityDetails.threads.length} 48 |
49 | )} 50 |161 | {body} 162 |
163 | ) 164 | }) 165 | FormMessage.displayName = "FormMessage" 166 | 167 | export { 168 | useFormField, 169 | Form, 170 | FormItem, 171 | FormLabel, 172 | FormControl, 173 | FormDescription, 174 | FormMessage, 175 | FormField, 176 | } 177 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | darkMode: ["class"], 4 | content: [ 5 | "./pages/**/*.{ts,tsx}", 6 | "./components/**/*.{ts,tsx}", 7 | "./app/**/*.{ts,tsx}", 8 | "./src/**/*.{ts,tsx}", 9 | ], 10 | theme: { 11 | container: { 12 | center: true, 13 | padding: "2rem", 14 | screens: { 15 | "2xl": "1400px", 16 | }, 17 | }, 18 | fontSize: { 19 | "heading1-bold": [ 20 | "36px", 21 | { 22 | lineHeight: "140%", 23 | fontWeight: "700", 24 | }, 25 | ], 26 | "heading1-semibold": [ 27 | "36px", 28 | { 29 | lineHeight: "140%", 30 | fontWeight: "600", 31 | }, 32 | ], 33 | "heading2-bold": [ 34 | "30px", 35 | { 36 | lineHeight: "140%", 37 | fontWeight: "700", 38 | }, 39 | ], 40 | "heading2-semibold": [ 41 | "30px", 42 | { 43 | lineHeight: "140%", 44 | fontWeight: "600", 45 | }, 46 | ], 47 | "heading3-bold": [ 48 | "24px", 49 | { 50 | lineHeight: "140%", 51 | fontWeight: "700", 52 | }, 53 | ], 54 | "heading4-medium": [ 55 | "20px", 56 | { 57 | lineHeight: "140%", 58 | fontWeight: "500", 59 | }, 60 | ], 61 | "body-bold": [ 62 | "18px", 63 | { 64 | lineHeight: "140%", 65 | fontWeight: "700", 66 | }, 67 | ], 68 | "body-semibold": [ 69 | "18px", 70 | { 71 | lineHeight: "140%", 72 | fontWeight: "600", 73 | }, 74 | ], 75 | "body-medium": [ 76 | "18px", 77 | { 78 | lineHeight: "140%", 79 | fontWeight: "500", 80 | }, 81 | ], 82 | "body-normal": [ 83 | "18px", 84 | { 85 | lineHeight: "140%", 86 | fontWeight: "400", 87 | }, 88 | ], 89 | "body1-bold": [ 90 | "18px", 91 | { 92 | lineHeight: "140%", 93 | fontWeight: "700", 94 | }, 95 | ], 96 | "base-regular": [ 97 | "16px", 98 | { 99 | lineHeight: "140%", 100 | fontWeight: "400", 101 | }, 102 | ], 103 | "base-medium": [ 104 | "16px", 105 | { 106 | lineHeight: "140%", 107 | fontWeight: "500", 108 | }, 109 | ], 110 | "base-semibold": [ 111 | "16px", 112 | { 113 | lineHeight: "140%", 114 | fontWeight: "600", 115 | }, 116 | ], 117 | "base1-semibold": [ 118 | "16px", 119 | { 120 | lineHeight: "140%", 121 | fontWeight: "600", 122 | }, 123 | ], 124 | "small-regular": [ 125 | "14px", 126 | { 127 | lineHeight: "140%", 128 | fontWeight: "400", 129 | }, 130 | ], 131 | "small-medium": [ 132 | "14px", 133 | { 134 | lineHeight: "140%", 135 | fontWeight: "500", 136 | }, 137 | ], 138 | "small-semibold": [ 139 | "14px", 140 | { 141 | lineHeight: "140%", 142 | fontWeight: "600", 143 | }, 144 | ], 145 | "subtle-medium": [ 146 | "12px", 147 | { 148 | lineHeight: "16px", 149 | fontWeight: "500", 150 | }, 151 | ], 152 | "subtle-semibold": [ 153 | "12px", 154 | { 155 | lineHeight: "16px", 156 | fontWeight: "600", 157 | }, 158 | ], 159 | "tiny-medium": [ 160 | "10px", 161 | { 162 | lineHeight: "140%", 163 | fontWeight: "500", 164 | }, 165 | ], 166 | "x-small-semibold": [ 167 | "7px", 168 | { 169 | lineHeight: "9.318px", 170 | fontWeight: "600", 171 | }, 172 | ], 173 | }, 174 | extend: { 175 | colors: { 176 | "primary-500": "#877EFF", 177 | "secondary-500": "#FFB620", 178 | blue: "#0095F6", 179 | "logout-btn": "#FF5A5A", 180 | "navbar-menu": "rgba(16, 16, 18, 0.6)", 181 | "dark-1": "#000000", 182 | "dark-2": "#121417", 183 | "dark-3": "#101012", 184 | "dark-4": "#1F1F22", 185 | "light-1": "#FFFFFF", 186 | "light-2": "#EFEFEF", 187 | "light-3": "#7878A3", 188 | "light-4": "#5C5C7B", 189 | "gray-1": "#697C89", 190 | glassmorphism: "rgba(16, 16, 18, 0.60)", 191 | }, 192 | boxShadow: { 193 | "count-badge": "0px 0px 6px 2px rgba(219, 188, 159, 0.30)", 194 | "groups-sidebar": "-30px 0px 60px 0px rgba(28, 28, 31, 0.50)", 195 | }, 196 | screens: { 197 | xs: "400px", 198 | }, 199 | keyframes: { 200 | "accordion-down": { 201 | from: { height: 0 }, 202 | to: { height: "var(--radix-accordion-content-height)" }, 203 | }, 204 | "accordion-up": { 205 | from: { height: "var(--radix-accordion-content-height)" }, 206 | to: { height: 0 }, 207 | }, 208 | }, 209 | animation: { 210 | "accordion-down": "accordion-down 0.2s ease-out", 211 | "accordion-up": "accordion-up 0.2s ease-out", 212 | }, 213 | }, 214 | }, 215 | plugins: [require("tailwindcss-animate")], 216 | }; 217 | -------------------------------------------------------------------------------- /lib/actions/user.actions.ts: -------------------------------------------------------------------------------- 1 | "use server"; 2 | 3 | import { FilterQuery, SortOrder } from "mongoose"; 4 | import { revalidatePath } from "next/cache"; 5 | 6 | import Community from "../models/community.model"; 7 | import Thread from "../models/thread.model"; 8 | import User from "../models/user.model"; 9 | 10 | import { connectToDB } from "../mongoose"; 11 | 12 | export async function fetchUser(userId: string) { 13 | try { 14 | connectToDB(); 15 | 16 | return await User.findOne({ id: userId }).populate({ 17 | path: "communities", 18 | model: Community, 19 | }); 20 | } catch (error: any) { 21 | throw new Error(`Failed to fetch user: ${error.message}`); 22 | } 23 | } 24 | 25 | interface Params { 26 | userId: string; 27 | username: string; 28 | name: string; 29 | bio: string; 30 | image: string; 31 | path: string; 32 | } 33 | 34 | export async function updateUser({ 35 | userId, 36 | bio, 37 | name, 38 | path, 39 | username, 40 | image, 41 | }: Params): Promise{content}
71 | 72 |109 | {comments.length} repl{comments.length > 1 ? "ies" : "y"} 110 |
111 | 112 | )} 113 |144 | {comments.length} repl{comments.length > 1 ? "ies" : "y"} 145 |
146 | 147 |156 | {formatDateString(createdAt)} 157 | {community && ` - ${community.name} Community`} 158 |
159 | 160 |