From 9c65a9c271dfda5ea17c9d909bc9e7e6d0c040ab Mon Sep 17 00:00:00 2001
From: l3wdfut4pwr
Date: Fri, 3 Apr 2026 23:59:33 +0300
Subject: add profile
---
src/app/globals.css | 48 ++++++++++++-
src/app/profile/[username]/page.tsx | 83 +++++++++++++++++++++++
src/app/profile/page.tsx | 3 -
src/components/header/ProfileOrLogin.tsx | 6 +-
src/components/header/authdialog/RegisterForm.tsx | 6 +-
src/components/settings/ProfilePage.tsx | 20 +-----
src/lib/api/user.ts | 13 ++++
src/lib/contexts/Auth.context.tsx | 30 +++++++-
8 files changed, 178 insertions(+), 31 deletions(-)
create mode 100644 src/app/profile/[username]/page.tsx
delete mode 100644 src/app/profile/page.tsx
create mode 100644 src/lib/api/user.ts
(limited to 'src')
diff --git a/src/app/globals.css b/src/app/globals.css
index 5ca3a6b..ca0c3c7 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -27,7 +27,6 @@
--light-violet: #8784c9;
--dark-indigo: #0d0c1c;
--red: #e64c4f;
-
--radius: 0.625rem;
--card: oklch(1 0 0);
--card-foreground: oklch(0.13 0.028 261.692);
@@ -106,6 +105,53 @@
--radius-4xl: calc(var(--radius) + 16px);
}
+@layer utilities {
+ .gradient-0 {
+ background-image: linear-gradient(89.91deg, #8784c9 0%, #464199 99.92%);
+ }
+ .gradient-1 {
+ background-image: linear-gradient(
+ 284.32deg,
+ #ffafbd 20.33%,
+ #dae2f8 79.67%
+ );
+ }
+ .gradient-2 {
+ background-image: linear-gradient(267.9deg, #473b7b 0%, #30d2be 100%);
+ }
+ .gradient-3 {
+ background-image: linear-gradient(88.87deg, #c33764 0%, #1d2671 100%);
+ }
+ .gradient-4 {
+ background-image: linear-gradient(267.9deg, #134e5e 0%, #71b280 100%);
+ }
+ .gradient-5 {
+ background-image: linear-gradient(87.9deg, #423aa2 0%, #100626 100%);
+ }
+ .gradient-6 {
+ background-image: linear-gradient(87.9deg, #edf3f6 0%, #d9eaf4 100%);
+ }
+ .gradient-7 {
+ background-image: linear-gradient(
+ 284.32deg,
+ #212121 20.33%,
+ #454545 79.67%
+ );
+ }
+ .gradient-8 {
+ background-image: linear-gradient(88.87deg, #610000 0%, #190a05 100%);
+ }
+ .gradient-9 {
+ background-image: linear-gradient(87.9deg, #ffc500 0%, #c21500 100%);
+ }
+ .gradient-10 {
+ background-image: linear-gradient(270deg, #6a11cb 0%, #69a1ff 100%);
+ }
+ .gradient-11 {
+ background-image: linear-gradient(267.9deg, #182848 0%, #4b6cb7 100%);
+ }
+}
+
@layer base {
* {
@apply border-violet outline-ring/50;
diff --git a/src/app/profile/[username]/page.tsx b/src/app/profile/[username]/page.tsx
new file mode 100644
index 0000000..cad11bb
--- /dev/null
+++ b/src/app/profile/[username]/page.tsx
@@ -0,0 +1,83 @@
+import Image from 'next/image';
+import { Button } from '@/components/ui';
+import { getUserByUsername } from '@/lib/api/user';
+import { User } from '@/lib/contexts/Auth.context';
+interface ProfilePageProps {
+ params: Promise<{ username: string }>;
+}
+
+export default async function Profile({ params }: ProfilePageProps) {
+ const { username } = await params;
+
+ const profileUser: User = await getUserByUsername(username);
+ const icons = [
+ 'facebook',
+ 'pinterest',
+ 'discord',
+ 'artstation',
+ 'behance',
+ 'instagram',
+ ] as const;
+
+ type IconKey = (typeof icons)[number];
+ return (
+ <>
+
+
+
+
+
+
+ {profileUser.username}
+
+
+
+
+ {profileUser.profile?.publications_count ?? 0}{' '}
+ публикаций
+
+
+ {profileUser.profile?.collections_count ?? 0}{' '}
+ коллекций
+
+
+ {profileUser.profile?.followers_count ?? 0}{' '}
+ подписчиков
+
+
+ {profileUser.profile?.following_count ?? 0}{' '}
+ подписок
+
+
+
+
{profileUser.description}
+
+
+ {icons
+ .filter(
+ (icon: IconKey) =>
+ profileUser.integrations?.[icon],
+ )
+ .map((icon: IconKey) => (
+
+
+
+ ))}{' '}
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx
deleted file mode 100644
index 17e3f62..0000000
--- a/src/app/profile/page.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function Profile() {
- return <>>;
-}
diff --git a/src/components/header/ProfileOrLogin.tsx b/src/components/header/ProfileOrLogin.tsx
index 416418b..68c81f6 100644
--- a/src/components/header/ProfileOrLogin.tsx
+++ b/src/components/header/ProfileOrLogin.tsx
@@ -21,11 +21,11 @@ export function ProfileOrLogin() {
);
}
-
+ const profileLink = `/profile/${user.username}`;
return (
-
+
@@ -56,11 +41,10 @@ export default function ProfilePage() {
- {gradients.map((gradient, index) => (
+ {Array.from({ length: 12 }).map((_, index) => (
))}
diff --git a/src/lib/api/user.ts b/src/lib/api/user.ts
new file mode 100644
index 0000000..86dfce8
--- /dev/null
+++ b/src/lib/api/user.ts
@@ -0,0 +1,13 @@
+const API_URL = process.env.NEXT_PUBLIC_API_URL;
+
+export async function getUserByUsername(username: string) {
+ if (!username) throw new Error('Username is required');
+
+ const res = await fetch(`${API_URL}/api/users/${username}`, {
+ cache: 'no-store',
+ });
+
+ if (!res.ok) throw new Error(`User not found: ${username}`);
+
+ return res.json();
+}
diff --git a/src/lib/contexts/Auth.context.tsx b/src/lib/contexts/Auth.context.tsx
index fbf2e24..4e567ba 100644
--- a/src/lib/contexts/Auth.context.tsx
+++ b/src/lib/contexts/Auth.context.tsx
@@ -4,12 +4,38 @@ import React, { createContext, useState, useContext, useEffect } from 'react';
export type User = {
id: number;
username: string;
+ email: string;
+ password?: string;
avatar?: string;
banner_file?: string;
+ description?: string;
premium?: boolean;
is_banned?: boolean;
is_moderator?: boolean;
+ token_version?: number;
+ profile?: {
+ id: number;
+ user_id: number;
+ avatar_file?: string;
+ banner_file?: string;
+ description?: string;
+ publications_count?: number;
+ collections_count?: number;
+ subscriptions_count?: number;
+ followers_count?: number;
+ following_count?: number;
+ };
+ integrations?: {
+ facebook?: string | null;
+ pinterest?: string | null;
+ discord?: string | null;
+ artstation?: string | null;
+ x?: string | null; // Twitter/X
+ behance?: string | null;
+ instagram?: string | null;
+ };
};
+
interface AuthContextType {
user: User | null;
setUser: (user: User | null) => void;
@@ -33,7 +59,9 @@ export const AuthContextProvider = ({ children }: React.PropsWithChildren) => {
if (!res.ok) return;
const userData = await res.json();
setUser(userData);
- } catch {}
+ } catch (err) {
+ console.error('Error fetching user:', err);
+ }
};
fetchUser();
--
cgit v1.3-3-g829e