diff --git a/app/api/utils.js b/app/api/utils.js
index 2d7ce12..c106e54 100644
--- a/app/api/utils.js
+++ b/app/api/utils.js
@@ -84,6 +84,11 @@ export function numberDeclension(number, one, two, five) {
if ([5, 6, 7, 8, 9, 0].includes(last_num)) return five;
}
+export function unixToDate(unix) {
+ const date = new Date(unix * 1000);
+ return date.toLocaleString("ru-RU");
+}
+
export function sinceUnixDate(unixInSeconds) {
const unix = Math.floor(unixInSeconds * 1000);
const date = new Date(unix);
@@ -108,3 +113,14 @@ export function sinceUnixDate(unixInSeconds) {
return date.toLocaleString("ru-RU").split(",")[0];
}
+
+export function minutesToTime(min) {
+ const d = Math.floor(min / 1440); // 60*24
+ const h = Math.floor((min - d * 1440) / 60);
+ const m = Math.round(min % 60);
+
+ var dDisplay = d > 0 ? `${d} ${numberDeclension(d, "день", "дня", "дней")}, ` : "";
+ var hDisplay = h > 0 ? `${h} ${numberDeclension(h, "час", "часа", "часов")}, ` : "";
+ var mDisplay = m > 0 ? `${m} ${numberDeclension(m, "минута", "минуты", "минут")}` : "";
+ return dDisplay + hDisplay + mDisplay;
+}
diff --git a/app/components/Chip/Chip.jsx b/app/components/Chip/Chip.jsx
new file mode 100644
index 0000000..34ebb55
--- /dev/null
+++ b/app/components/Chip/Chip.jsx
@@ -0,0 +1,12 @@
+export const Chip = (props) => {
+ return (
+
+
+ {props.name}
+ {props.name && props.devider ? props.devider : " "}
+ {props.name_2}
+
+
+ );
+ };
+
\ No newline at end of file
diff --git a/app/components/Navbar/Navbar.jsx b/app/components/Navbar/Navbar.jsx
index c479dc3..9049fa0 100644
--- a/app/components/Navbar/Navbar.jsx
+++ b/app/components/Navbar/Navbar.jsx
@@ -106,16 +106,13 @@ export const Navbar = () => {
"ml-1 w-4 h-4 [transform:rotateX(180deg)] sm:transform-none",
}}
>
- {
- userStore.logout();
- }}
- className="text-sm md:text-base"
- >
-
- Выйти
+
+
+
+ Профиль
+
{navLinks.map((link) => {
return (
@@ -145,6 +142,17 @@ export const Navbar = () => {
);
})}
+ {
+ userStore.logout();
+ }}
+ className="text-sm md:text-base"
+ >
+
+ Выйти
+
) : (
diff --git a/app/components/ReleaseLink/Chip.jsx b/app/components/ReleaseLink/Chip.jsx
deleted file mode 100644
index 282026e..0000000
--- a/app/components/ReleaseLink/Chip.jsx
+++ /dev/null
@@ -1,11 +0,0 @@
-export const Chip = (props) => {
- return (
-
-
- {props.name}
- {props.name && props.devider ? props.devider : " "}
- {props.name_2}
-
-
- );
-};
diff --git a/app/components/ReleaseLink/ReleaseLink.jsx b/app/components/ReleaseLink/ReleaseLink.jsx
index ff38f74..80fd24b 100644
--- a/app/components/ReleaseLink/ReleaseLink.jsx
+++ b/app/components/ReleaseLink/ReleaseLink.jsx
@@ -1,6 +1,6 @@
import Link from "next/link";
import { sinceUnixDate } from "@/app/api/utils";
-import { Chip } from "./Chip";
+import { Chip } from "@/app/components/Chip/Chip";
export const ReleaseLink = (props) => {
const grade = props.grade.toFixed(1);
diff --git a/app/pages/Profile.jsx b/app/pages/Profile.jsx
new file mode 100644
index 0000000..4406d84
--- /dev/null
+++ b/app/pages/Profile.jsx
@@ -0,0 +1,293 @@
+"use client";
+import { useUserStore } from "@/app/store/auth";
+import { useEffect, useState } from "react";
+import { fetchDataViaGet } from "../api/utils";
+import { Spinner } from "../components/Spinner/Spinner";
+import { Avatar, Card, Button, Table } from "flowbite-react";
+import { Chip } from "../components/Chip/Chip";
+import { unixToDate, minutesToTime } from "../api/utils";
+import { ReleaseLink } from "../components/ReleaseLink/ReleaseLink";
+
+export const ProfilePage = (props) => {
+ const authUser = useUserStore((state) => state);
+ const [user, setUser] = useState(null);
+ const [isMyProfile, setIsMyProfile] = useState(false);
+
+ useEffect(() => {
+ async function _getData() {
+ let url = `/api/profile/${props.id}`;
+ if (authUser.token) {
+ url += `?token=${authUser.token}`;
+ }
+ const data = await fetchDataViaGet(url);
+ setUser(data.profile);
+ setIsMyProfile(data.is_my_profile);
+ }
+ _getData();
+ }, [authUser]);
+
+ if (!user) {
+ return (
+
+
+
+ );
+ }
+
+ const hasSocials =
+ user.vk_page != "" ||
+ user.tg_page != "" ||
+ user.tt_page != "" ||
+ user.inst_page != "" ||
+ user.discord_page != "" ||
+ false;
+ const socials = [
+ {
+ name: "vk",
+ nickname: user.vk_page,
+ icon: "fa6-brands--vk",
+ urlPrefix: "https://vk.com",
+ },
+ {
+ name: "telegram",
+ nickname: user.tg_page,
+ icon: "fa6-brands--telegram",
+ urlPrefix: "https://t.me",
+ },
+ {
+ name: "discord",
+ nickname: user.discord_page,
+ icon: "fa6-brands--discord",
+ },
+ {
+ name: "tiktok",
+ nickname: user.tt_page,
+ icon: "fa6-brands--tiktok",
+ urlPrefix: "https://tiktok.com",
+ },
+ {
+ name: "instagram",
+ nickname: user.inst_page,
+ icon: "fa6-brands--instagram",
+ urlPrefix: "https://instagram.com",
+ },
+ ];
+
+ return (
+
+
+
+
+ {isMyProfile && }
+ {user.is_banned && (
+
+ )}
+ {user.is_verified && (
+
+ )}
+ {/* {user.is_banned && } */}
+
+ {/* */}
+ {/* */}
+
+
+
+
{user.login}
+
+ {user.status}
+
+
+
+ {hasSocials && (
+
+ {socials.map((social) => {
+ if (!social.nickname) return null;
+ if (social.name == "discord") return (
+
+ )
+ return (
+
+ );
+ })}
+
+ )}
+
+
+
+ Активность
+
+
+
+
+ Регистрация
+
+
+ {unixToDate(user.register_date)}
+
+
+
+
+ Был(а) в сети
+
+
+ {unixToDate(user.last_activity_time)}
+
+
+
+
+ Комментарий
+
+
+ {user.comment_count}
+
+
+
+
+ друзей
+
+
+ {user.friend_count}
+
+
+
+
+ видео
+
+
+ {user.video_count}
+
+
+
+
+ коллекций
+
+
+ {user.collection_count}
+
+
+
+
+
+
+ Статистика
+
+
+
+
+
+ Просмотрено серий
+
+
+ {user.watched_episode_count}
+
+
+
+
+
+ Время просмотра
+
+
+ {minutesToTime(user.watched_time)}
+
+
+
+
+
+ {minutesToTime(user.watched_time)}
+
+
+
+
+
+ Смотрю
+
+
+ {user.watching_count}
+
+
+
+
+
+ В Планах
+
+
+ {user.plan_count}
+
+
+
+
+
+ Просмотрено
+
+
+ {user.completed_count}
+
+
+
+
+
+ Отложено
+
+
+ {user.hold_on_count}
+
+
+
+
+
+ Брошено
+
+
+ {user.dropped_count}
+
+
+
+
+
+
+
+
+
+ Недавно просмотренные
+
+ {user.history.map((release) => {
+ return ;
+ })}
+
+
+
+
+ );
+};
diff --git a/app/profile/[id]/page.js b/app/profile/[id]/page.js
new file mode 100644
index 0000000..5117077
--- /dev/null
+++ b/app/profile/[id]/page.js
@@ -0,0 +1,17 @@
+import { ProfilePage } from "@/app/pages/Profile";
+import { fetchDataViaGet } from "@/app/api/utils";
+import { ENDPOINTS } from "@/app/api/config";
+
+export async function generateMetadata({ params }) {
+ const id = params.id
+ const profile = await fetchDataViaGet(`${ENDPOINTS.user.profile}/${id}`);
+
+ return {
+ title: "Профиль " + profile.profile.login,
+ };
+}
+
+export default async function Search({ params }) {
+ const id = params.id
+ return ;
+}
diff --git a/app/profile/page.js b/app/profile/page.js
new file mode 100644
index 0000000..4bfa736
--- /dev/null
+++ b/app/profile/page.js
@@ -0,0 +1,14 @@
+"use client"
+import { useRouter } from "next/navigation";
+import { getJWT } from "../api/utils";
+
+export default function myProfile() {
+ const user = getJWT()
+ const router = useRouter()
+
+ if (!user) {
+ return router.push("/login")
+ } else {
+ return router.push(`/profile/${user.user_id}`)
+ }
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 6c1c26e..07a7fef 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,6 +18,7 @@
"zustand": "^4.5.4"
},
"devDependencies": {
+ "@iconify-json/fa6-brands": "^1.1.21",
"@iconify-json/material-symbols": "^1.1.83",
"@iconify-json/mdi": "^1.1.67",
"@iconify-json/twemoji": "^1.1.15",
@@ -190,6 +191,15 @@
"deprecated": "Use @eslint/object-schema instead",
"dev": true
},
+ "node_modules/@iconify-json/fa6-brands": {
+ "version": "1.1.21",
+ "resolved": "https://registry.npmjs.org/@iconify-json/fa6-brands/-/fa6-brands-1.1.21.tgz",
+ "integrity": "sha512-NS/BszVo8fUVpzA7/5b9tmkHzisZSUlm8kjdznk1Bux5p5QH3BxHZXrZUM5QsT90/7+omQC0EKukwf7H7nujZg==",
+ "dev": true,
+ "dependencies": {
+ "@iconify/types": "*"
+ }
+ },
"node_modules/@iconify-json/material-symbols": {
"version": "1.1.83",
"resolved": "https://registry.npmjs.org/@iconify-json/material-symbols/-/material-symbols-1.1.83.tgz",
diff --git a/package.json b/package.json
index d4378e3..fa0caa7 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"zustand": "^4.5.4"
},
"devDependencies": {
+ "@iconify-json/fa6-brands": "^1.1.21",
"@iconify-json/material-symbols": "^1.1.83",
"@iconify-json/mdi": "^1.1.67",
"@iconify-json/twemoji": "^1.1.15",
diff --git a/tailwind.config.js b/tailwind.config.js
index 7a860b4..d8dda9d 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -10,7 +10,7 @@ module.exports = {
flowbite.content(),
],
plugins: [
- addIconSelectors(["mdi", "material-symbols", "twemoji"]),
+ addIconSelectors(["mdi", "material-symbols", "twemoji", "fa6-brands"]),
require('tailwind-scrollbar'),
flowbite.plugin(),
],