diff --git a/src/webapp/app/(authenticated)/my-cards/error.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/cards/error.tsx
similarity index 100%
rename from src/webapp/app/(authenticated)/my-cards/error.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/cards/error.tsx
diff --git a/src/webapp/app/(authenticated)/collections/[collectionId]/layout.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/cards/layout.tsx
similarity index 86%
rename from src/webapp/app/(authenticated)/collections/[collectionId]/layout.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/cards/layout.tsx
index bb204ea7..89af4c97 100644
--- a/src/webapp/app/(authenticated)/collections/[collectionId]/layout.tsx
+++ b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/cards/layout.tsx
@@ -3,8 +3,8 @@ import type { Metadata } from 'next';
import { Fragment } from 'react';
export const metadata: Metadata = {
- title: 'Collection',
- description: 'Collection',
+ title: 'My Cards',
+ description: 'All my cards',
};
interface Props {
diff --git a/src/webapp/app/(authenticated)/my-cards/loading.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/cards/loading.tsx
similarity index 100%
rename from src/webapp/app/(authenticated)/my-cards/loading.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/cards/loading.tsx
diff --git a/src/webapp/app/(authenticated)/my-cards/page.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/cards/page.tsx
similarity index 100%
rename from src/webapp/app/(authenticated)/my-cards/page.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/cards/page.tsx
diff --git a/src/webapp/app/(authenticated)/collections/error.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/collections/error.tsx
similarity index 100%
rename from src/webapp/app/(authenticated)/collections/error.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/collections/error.tsx
diff --git a/src/webapp/app/(authenticated)/collections/layout.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/collections/layout.tsx
similarity index 78%
rename from src/webapp/app/(authenticated)/collections/layout.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/collections/layout.tsx
index 98351f2e..467e7667 100644
--- a/src/webapp/app/(authenticated)/collections/layout.tsx
+++ b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/collections/layout.tsx
@@ -12,10 +12,5 @@ interface Props {
}
export default function Layout(props: Props) {
- return (
-
-
- {props.children}
-
- );
+ return {props.children};
}
diff --git a/src/webapp/app/(authenticated)/collections/loading.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/collections/loading.tsx
similarity index 100%
rename from src/webapp/app/(authenticated)/collections/loading.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/collections/loading.tsx
diff --git a/src/webapp/app/(authenticated)/collections/page.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/collections/page.tsx
similarity index 100%
rename from src/webapp/app/(authenticated)/collections/page.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/collections/page.tsx
diff --git a/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/layout.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/layout.tsx
new file mode 100644
index 00000000..d082cc04
--- /dev/null
+++ b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/layout.tsx
@@ -0,0 +1,58 @@
+import { ApiClient } from '@/api-client/ApiClient';
+import Header from '@/components/navigation/header/Header';
+import ProfileHeader from '@/features/profile/components/profileHeader/ProfileHeader';
+import { getAccessTokenInServerComponent } from '@/services/auth';
+import { Button, Container, Stack, Text, Title } from '@mantine/core';
+import type { Metadata } from 'next';
+import Link from 'next/link';
+import { Fragment } from 'react';
+
+interface Props {
+ params: Promise<{ handle: string }>;
+ children: React.ReactNode;
+}
+
+export async function generateMetadata({ params }: Props): Promise {
+ const { handle } = await params;
+
+ return {
+ title: handle,
+ description: 'Profile',
+ };
+}
+
+export default async function Layout(props: Props) {
+ const { handle } = await props.params;
+ const accessToken = await getAccessTokenInServerComponent();
+ const apiClient = new ApiClient(
+ process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3000',
+ () => accessToken,
+ );
+ const data = await apiClient.getMyProfile();
+
+ // TODO: use profile endpoints to fetch profile information
+ // for now we'll use getMyProfile
+ if (!accessToken || data.handle !== handle) {
+ return (
+
+
+
+
+ Public profiles are coming soon!
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+ {props.children}
+
+ );
+}
diff --git a/src/webapp/app/(authenticated)/profile/[handle]/loading.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/loading.tsx
similarity index 100%
rename from src/webapp/app/(authenticated)/profile/[handle]/loading.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/loading.tsx
diff --git a/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/page.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/page.tsx
new file mode 100644
index 00000000..7d1e0b71
--- /dev/null
+++ b/src/webapp/app/(authenticated)/profile/[handle]/(withHeader)/page.tsx
@@ -0,0 +1,3 @@
+export default function Page() {
+ return <>>;
+}
diff --git a/src/webapp/app/(authenticated)/collections/[collectionId]/error.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withoutHeader)/collections/[collectionId]/error.tsx
similarity index 100%
rename from src/webapp/app/(authenticated)/collections/[collectionId]/error.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withoutHeader)/collections/[collectionId]/error.tsx
diff --git a/src/webapp/app/(authenticated)/my-cards/layout.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withoutHeader)/collections/[collectionId]/layout.tsx
similarity index 51%
rename from src/webapp/app/(authenticated)/my-cards/layout.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withoutHeader)/collections/[collectionId]/layout.tsx
index aea0cf5a..1e8e7579 100644
--- a/src/webapp/app/(authenticated)/my-cards/layout.tsx
+++ b/src/webapp/app/(authenticated)/profile/[handle]/(withoutHeader)/collections/[collectionId]/layout.tsx
@@ -1,10 +1,9 @@
-import Header from '@/components/navigation/header/Header';
import type { Metadata } from 'next';
import { Fragment } from 'react';
export const metadata: Metadata = {
- title: 'My Cards',
- description: 'All my cards',
+ title: 'Collection',
+ description: 'Collection',
};
interface Props {
@@ -12,10 +11,5 @@ interface Props {
}
export default function Layout(props: Props) {
- return (
-
-
- {props.children}
-
- );
+ return {props.children};
}
diff --git a/src/webapp/app/(authenticated)/collections/[collectionId]/loading.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withoutHeader)/collections/[collectionId]/loading.tsx
similarity index 100%
rename from src/webapp/app/(authenticated)/collections/[collectionId]/loading.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withoutHeader)/collections/[collectionId]/loading.tsx
diff --git a/src/webapp/app/(authenticated)/collections/[collectionId]/page.tsx b/src/webapp/app/(authenticated)/profile/[handle]/(withoutHeader)/collections/[collectionId]/page.tsx
similarity index 100%
rename from src/webapp/app/(authenticated)/collections/[collectionId]/page.tsx
rename to src/webapp/app/(authenticated)/profile/[handle]/(withoutHeader)/collections/[collectionId]/page.tsx
diff --git a/src/webapp/app/(authenticated)/profile/[handle]/layout.tsx b/src/webapp/app/(authenticated)/profile/[handle]/layout.tsx
deleted file mode 100644
index baff099f..00000000
--- a/src/webapp/app/(authenticated)/profile/[handle]/layout.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import Header from '@/components/navigation/header/Header';
-import type { Metadata } from 'next';
-import { Fragment } from 'react';
-
-interface Props {
- params: Promise<{ handle: string }>;
- children: React.ReactNode;
-}
-
-export async function generateMetadata({ params }: Props): Promise {
- const { handle } = await params;
-
- return {
- title: handle,
- description: 'Profile',
- };
-}
-
-export default async function Layout(props: Props) {
- return (
-
-
- {props.children}
-
- );
-}
diff --git a/src/webapp/app/(authenticated)/profile/[handle]/page.tsx b/src/webapp/app/(authenticated)/profile/[handle]/page.tsx
deleted file mode 100644
index 4ab89d1f..00000000
--- a/src/webapp/app/(authenticated)/profile/[handle]/page.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-'use client';
-
-import { useParams } from 'next/navigation';
-import { Stack, Title, Text, Card, Center } from '@mantine/core';
-
-export default function ProfilePage() {
- const params = useParams();
- const handle = params.handle as string;
-
- return (
-
-
-
- Profile Page
- Profile for @{handle} - Coming Soon!
-
- This page will show user profile information and their public
- activity.
-
-
-
-
- );
-}
diff --git a/src/webapp/app/(authenticated)/profile/page.tsx b/src/webapp/app/(authenticated)/profile/page.tsx
index 19d39e56..fc84468e 100644
--- a/src/webapp/app/(authenticated)/profile/page.tsx
+++ b/src/webapp/app/(authenticated)/profile/page.tsx
@@ -1,14 +1,6 @@
-'use client';
-
-import Header from '@/components/navigation/header/Header';
-import ProfileContainer from '@/features/profile/containers/profileContainer/ProfileContainer';
-import { Fragment } from 'react';
+import { redirect } from 'next/navigation';
export default function Page() {
- return (
-
-
-
-
- );
+ // page is left empty, redirect to home if [handle] isn't provided
+ redirect('/home');
}
diff --git a/src/webapp/components/navigation/navbar/Navbar.tsx b/src/webapp/components/navigation/navbar/Navbar.tsx
index 9cae1a56..5856817d 100644
--- a/src/webapp/components/navigation/navbar/Navbar.tsx
+++ b/src/webapp/components/navigation/navbar/Navbar.tsx
@@ -23,9 +23,11 @@ import CollectionsNavListSkeleton from '@/features/collections/components/collec
import NavbarToggle from '../NavbarToggle';
import { FiPlus } from 'react-icons/fi';
import AddCardDrawer from '@/features/cards/components/addCardDrawer/AddCardDrawer';
+import useMyProfile from '@/features/profile/lib/queries/useMyProfile';
export default function Navbar() {
const [openAddDrawer, setOpenAddDrawer] = useState(false);
+ const { data: profile } = useMyProfile();
return (
@@ -45,8 +47,8 @@ export default function Navbar() {
} />
}
/>
- My Cards
+ Cards
{allCards.length > 0 ? (
diff --git a/src/webapp/features/cards/containers/myCardsContainer/Skeleton.MyCardsContainer.tsx b/src/webapp/features/cards/containers/myCardsContainer/Skeleton.MyCardsContainer.tsx
index fe3e114e..8833b93c 100644
--- a/src/webapp/features/cards/containers/myCardsContainer/Skeleton.MyCardsContainer.tsx
+++ b/src/webapp/features/cards/containers/myCardsContainer/Skeleton.MyCardsContainer.tsx
@@ -5,7 +5,7 @@ export default function MyCardsContainerSkeleton() {
return (
- My Cards
+ Cards
{Array.from({ length: 8 }).map((_, i) => (
diff --git a/src/webapp/features/collections/components/addToCollectionModal/CardToBeAddedPreview.tsx b/src/webapp/features/collections/components/addToCollectionModal/CardToBeAddedPreview.tsx
index e6839159..e51c8566 100644
--- a/src/webapp/features/collections/components/addToCollectionModal/CardToBeAddedPreview.tsx
+++ b/src/webapp/features/collections/components/addToCollectionModal/CardToBeAddedPreview.tsx
@@ -74,7 +74,7 @@ export default function CardToBeAddedPreview(props: Props) {
router.push(`/collections/${collection.id}`)}
+ onClick={() =>
+ router.push(
+ `/profile/${collection.createdBy.handle}/collections/${collection.id}`,
+ )
+ }
radius={'lg'}
p={'sm'}
style={{ cursor: 'pointer' }}
diff --git a/src/webapp/features/collections/components/collectionsNavList/CollectionsNavList.tsx b/src/webapp/features/collections/components/collectionsNavList/CollectionsNavList.tsx
index f1271b70..4256adea 100644
--- a/src/webapp/features/collections/components/collectionsNavList/CollectionsNavList.tsx
+++ b/src/webapp/features/collections/components/collectionsNavList/CollectionsNavList.tsx
@@ -6,9 +6,11 @@ import useCollections from '../../lib/queries/useCollections';
import { useToggle } from '@mantine/hooks';
import CollectionsNavListError from './Error.CollectionsNavList';
import CreateCollectionShortcut from '../createCollectionShortcut/CreateCollectionShortcut';
+import useMyProfile from '@/features/profile/lib/queries/useMyProfile';
export default function CollectionsNavList() {
const { data, error } = useCollections({ limit: 30 });
+ const { data: profile } = useMyProfile();
const [opened, toggleMenu] = useToggle([true, false]);
if (error) {
@@ -31,7 +33,7 @@ export default function CollectionsNavList() {
))}
diff --git a/src/webapp/features/collections/components/deleteCollectionModal/DeleteCollectionModal.tsx b/src/webapp/features/collections/components/deleteCollectionModal/DeleteCollectionModal.tsx
index fd64237e..f9f4f87b 100644
--- a/src/webapp/features/collections/components/deleteCollectionModal/DeleteCollectionModal.tsx
+++ b/src/webapp/features/collections/components/deleteCollectionModal/DeleteCollectionModal.tsx
@@ -16,9 +16,9 @@ export default function DeleteCollectionModal(props: Props) {
const handleDeleteCollection = () => {
deleteCollection.mutate(props.collectionId, {
- onSuccess: () => {
+ onSuccess: (fes) => {
props.onClose();
- router.push('/collections');
+ router.push('./');
},
onError: () => {
notifications.show({
diff --git a/src/webapp/features/feeds/components/feedActivityStatus/FeedActivityStatus.tsx b/src/webapp/features/feeds/components/feedActivityStatus/FeedActivityStatus.tsx
index c87ad705..c0286af6 100644
--- a/src/webapp/features/feeds/components/feedActivityStatus/FeedActivityStatus.tsx
+++ b/src/webapp/features/feeds/components/feedActivityStatus/FeedActivityStatus.tsx
@@ -32,14 +32,16 @@ export default function FeedActivityStatus(props: Props) {
added to{' '}
{displayedCollections.map((collection, index) => (
+ {/* TODO: use collection creator's handle to direct to profile/creatorHandle/collections/id */}
{collection.name}
+
{index < displayedCollections.length - 1 ? ' and ' : ''}
))}
diff --git a/src/webapp/features/home/containers/homeContainer/HomeContainer.tsx b/src/webapp/features/home/containers/homeContainer/HomeContainer.tsx
index c344800b..dc1dd58a 100644
--- a/src/webapp/features/home/containers/homeContainer/HomeContainer.tsx
+++ b/src/webapp/features/home/containers/homeContainer/HomeContainer.tsx
@@ -21,10 +21,12 @@ import { useState } from 'react';
import { BiCollection, BiPlus } from 'react-icons/bi';
import { FaRegNoteSticky } from 'react-icons/fa6';
import AddCardDrawer from '@/features/cards/components/addCardDrawer/AddCardDrawer';
+import useMyProfile from '@/features/profile/lib/queries/useMyProfile';
export default function HomeContainer() {
const { data: collectionsData } = useCollections({ limit: 4 });
const { data: myCardsData } = useMyCards({ limit: 4 });
+ const { data: profile } = useMyProfile();
const [showCollectionDrawer, setShowCollectionDrawer] = useState(false);
const [showAddDrawer, setShowAddDrawer] = useState(false);
@@ -46,7 +48,12 @@ export default function HomeContainer() {
Collections
-
+
View all
@@ -80,9 +87,14 @@ export default function HomeContainer() {
- My Cards
+ Cards
-
+
View all
diff --git a/src/webapp/features/home/containers/homeContainer/Skeleton.HomeContainer.tsx b/src/webapp/features/home/containers/homeContainer/Skeleton.HomeContainer.tsx
index af488932..cb7f82e4 100644
--- a/src/webapp/features/home/containers/homeContainer/Skeleton.HomeContainer.tsx
+++ b/src/webapp/features/home/containers/homeContainer/Skeleton.HomeContainer.tsx
@@ -1,14 +1,13 @@
import {
- Anchor,
Container,
Grid,
GridCol,
Group,
SimpleGrid,
+ Skeleton,
Stack,
Title,
} from '@mantine/core';
-import Link from 'next/link';
import { BiCollection } from 'react-icons/bi';
import { FaRegNoteSticky } from 'react-icons/fa6';
import UrlCardSkeleton from '@/features/cards/components/urlCard/Skeleton.UrlCard';
@@ -28,9 +27,7 @@ export default function HomeContainerSkeleton() {
Collections
-
- View all
-
+
@@ -45,11 +42,9 @@ export default function HomeContainerSkeleton() {
- My Cards
+ Cards
-
- View all
-
+
diff --git a/src/webapp/features/profile/components/profileHeader/ProfileHeader.tsx b/src/webapp/features/profile/components/profileHeader/ProfileHeader.tsx
new file mode 100644
index 00000000..bacf3ae6
--- /dev/null
+++ b/src/webapp/features/profile/components/profileHeader/ProfileHeader.tsx
@@ -0,0 +1,63 @@
+import { ApiClient } from '@/api-client/ApiClient';
+import { getAccessTokenInServerComponent } from '@/services/auth';
+import {
+ Container,
+ Stack,
+ Group,
+ Avatar,
+ Text,
+ Title,
+ Button,
+} from '@mantine/core';
+import { FaBluesky } from 'react-icons/fa6';
+
+interface Props {
+ handle: string;
+}
+
+export default async function ProfileHeader(props: Props) {
+ const accessToken = await getAccessTokenInServerComponent();
+
+ const apiClient = new ApiClient(
+ process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3000',
+ () => accessToken,
+ );
+ const data = await apiClient.getMyProfile();
+
+ return (
+
+
+
+
+
+
+
+
+ {data.name}
+
+
+ {data.handle}
+
+
+ {data.description && {data.description}}
+
+
+ }
+ >
+ @{data.handle}
+
+
+
+
+ );
+}
diff --git a/src/webapp/features/profile/components/profileMenu/ProfileMenu.tsx b/src/webapp/features/profile/components/profileMenu/ProfileMenu.tsx
index bb66fa26..467cbd1c 100644
--- a/src/webapp/features/profile/components/profileMenu/ProfileMenu.tsx
+++ b/src/webapp/features/profile/components/profileMenu/ProfileMenu.tsx
@@ -58,7 +58,7 @@ export default function ProfileMenu() {
-
+