diff --git a/pages/[username]/pagina/[page]/index.public.js b/pages/[username]/conteudos/[page]/index.public.js
similarity index 64%
rename from pages/[username]/pagina/[page]/index.public.js
rename to pages/[username]/conteudos/[page]/index.public.js
index f2464a2da..5af9b75d1 100644
--- a/pages/[username]/pagina/[page]/index.public.js
+++ b/pages/[username]/conteudos/[page]/index.public.js
@@ -1,24 +1,41 @@
+import { useRouter } from 'next/router';
import { getStaticPropsRevalidate } from 'next-swr';
-import { ContentList, DefaultLayout } from '@/TabNewsUI';
+import { ContentList, DefaultLayout, UserHeader } from '@/TabNewsUI';
+import { FaUser } from '@/TabNewsUI/icons';
import { NotFoundError } from 'errors';
import authorization from 'models/authorization.js';
import content from 'models/content.js';
import removeMarkdown from 'models/remove-markdown.js';
import user from 'models/user.js';
import validator from 'models/validator.js';
+import { useUser } from 'pages/interface';
export default function Home({ contentListFound, pagination, username }) {
+ const { push } = useRouter();
+ const { user, isLoading } = useUser();
+ const isAuthenticatedUser = user && user.username === username;
+
return (
- <>
-
-
-
- >
+
+
+
+ push('/publicar'),
+ },
+ }}
+ />
+
);
}
@@ -55,6 +72,7 @@ export const getStaticProps = getStaticPropsRevalidate(async (context) => {
results = await content.findWithStrategy({
strategy: 'new',
where: {
+ parent_id: null,
owner_id: secureUserFound.id,
status: 'published',
},
diff --git a/pages/[username]/index.public.js b/pages/[username]/index.public.js
index 15c94630c..78752c042 100644
--- a/pages/[username]/index.public.js
+++ b/pages/[username]/index.public.js
@@ -1,49 +1,44 @@
-import { useRouter } from 'next/router';
import { getStaticPropsRevalidate } from 'next-swr';
import { useState } from 'react';
import useSWR from 'swr';
import {
- ActionList,
- ActionMenu,
Box,
- ContentList,
+ Button,
DefaultLayout,
Flash,
- IconButton,
Label,
LabelGroup,
- NavItem,
- NavList,
- Pagehead,
+ Link,
PastTime,
TabCashCount,
TabCoinCount,
- Text,
useConfirm,
+ UserHeader,
Viewer,
} from '@/TabNewsUI';
-import { CircleSlashIcon, FaUser, GearIcon, KebabHorizontalIcon } from '@/TabNewsUI/icons';
+import { CircleSlashIcon, GearIcon } from '@/TabNewsUI/icons';
import { NotFoundError } from 'errors';
import authorization from 'models/authorization.js';
import content from 'models/content.js';
-import removeMarkdown from 'models/remove-markdown.js';
import user from 'models/user.js';
import validator from 'models/validator.js';
import { useUser } from 'pages/interface';
-export default function Home({ contentListFound, pagination, userFound: userFoundFallback }) {
+export default function Home({ userFound: userFoundFallback }) {
const { data: userFound, mutate: userFoundMutate } = useSWR(`/api/v1/users/${userFoundFallback.username}`, {
fallbackData: userFoundFallback,
revalidateOnMount: false,
});
- const { user, isLoading } = useUser();
- const { push } = useRouter();
+ const { user } = useUser();
const confirm = useConfirm();
const [globalErrorMessage, setGlobalErrorMessage] = useState(false);
const isAuthenticatedUser = user && user.username === userFound.username;
+ const canNuke =
+ !isAuthenticatedUser && user?.features?.includes('ban:user') && !userFound?.features?.includes('nuked');
+ const canUpdate = isAuthenticatedUser && user?.features?.includes('update:user');
async function handleClickNuke() {
setGlobalErrorMessage(null);
@@ -90,115 +85,73 @@ export default function Home({ contentListFound, pagination, userFound: userFoun
return;
}
- function OptionsMenu() {
- const canNuke =
- !isAuthenticatedUser && user?.features?.includes('ban:user') && !userFound?.features?.includes('nuked');
- const canUpdate = isAuthenticatedUser && user?.features?.includes('update:user');
- if (!canNuke && !canUpdate) {
- return null;
- }
-
- return (
-
-
-
-
-
-
- {canUpdate && (
-
-
-
-
- Editar perfil
-
- )}
- {canNuke && (
-
-
-
-
- Nuke
-
- )}
-
-
-
- );
- }
-
function UserFeatures() {
if (!userFound?.features?.length) return null;
return (
-
+
{userFound.features.includes('nuked') && }
);
}
return (
- <>
-
- {globalErrorMessage && (
-
- {globalErrorMessage}
-
- )}
-
-
-
-
- {userFound.username}
-
-
-
-
-
- {' · '}
- `Membro há ${date}.`} sx={{ pl: 2 }} />
-
-
- {OptionsMenu()}
-
-
- {userFound.description && (
-
-
-
- )}
-
- push('/publicar'),
- },
- }}
- />
-
- >
+
+ {globalErrorMessage && (
+
+ {globalErrorMessage}
+
+ )}
+
+
+
+
+
+
+
+ {' · '}
+ `Membro há ${date}`} sx={{ pl: 2 }} />
+
+
+
+
+ {canUpdate && (
+
+ )}
+ {canNuke && (
+
+ )}
+
+
+
+ {userFound.description && (
+
+
+
+ )}
+
);
}
@@ -245,23 +198,12 @@ export const getStaticProps = getStaticPropsRevalidate(async (context) => {
};
}
- let results;
let secureUserFound;
try {
const userFound = await user.findOneByUsername(context.params.username, { withBalance: true });
secureUserFound = authorization.filterOutput(userTryingToGet, 'read:user', userFound);
-
- results = await content.findWithStrategy({
- strategy: 'new',
- where: {
- owner_id: secureUserFound.id,
- status: 'published',
- },
- page: context.params.page,
- per_page: context.params.per_page,
- });
} catch (error) {
// `user` model will throw a `NotFoundError` if the user is not found.
if (error instanceof NotFoundError) {
@@ -274,22 +216,8 @@ export const getStaticProps = getStaticPropsRevalidate(async (context) => {
throw error;
}
- const contentListFound = results.rows;
-
- const secureContentListFound = authorization.filterOutput(userTryingToGet, 'read:content:list', contentListFound);
-
- for (const content of secureContentListFound) {
- if (content.parent_id) {
- content.body = removeMarkdown(content.body, { maxLength: 255 });
- } else {
- delete content.body;
- }
- }
-
return {
props: {
- contentListFound: JSON.parse(JSON.stringify(secureContentListFound)),
- pagination: results.pagination,
userFound: JSON.parse(JSON.stringify(secureUserFound)),
},
diff --git a/pages/[username]/respostas/[page]/index.public.js b/pages/[username]/respostas/[page]/index.public.js
new file mode 100644
index 000000000..b1b036f50
--- /dev/null
+++ b/pages/[username]/respostas/[page]/index.public.js
@@ -0,0 +1,114 @@
+import { useRouter } from 'next/router';
+import { getStaticPropsRevalidate } from 'next-swr';
+
+import { ContentList, DefaultLayout, UserHeader } from '@/TabNewsUI';
+import { FaUser } from '@/TabNewsUI/icons';
+import { NotFoundError } from 'errors';
+import authorization from 'models/authorization.js';
+import content from 'models/content.js';
+import removeMarkdown from 'models/remove-markdown.js';
+import user from 'models/user.js';
+import validator from 'models/validator.js';
+import { useUser } from 'pages/interface';
+
+export default function Home({ contentListFound, pagination, username }) {
+ const { push } = useRouter();
+ const { user, isLoading } = useUser();
+ const isAuthenticatedUser = user && user.username === username;
+
+ return (
+
+
+
+ push('/publicar'),
+ },
+ }}
+ />
+
+ );
+}
+
+export async function getStaticPaths() {
+ return {
+ paths: [],
+ fallback: 'blocking',
+ };
+}
+
+export const getStaticProps = getStaticPropsRevalidate(async (context) => {
+ const userTryingToGet = user.createAnonymous();
+
+ try {
+ context.params = validator(context.params, {
+ username: 'required',
+ page: 'optional',
+ per_page: 'optional',
+ });
+ } catch (error) {
+ return {
+ notFound: true,
+ };
+ }
+
+ let results;
+ let secureUserFound;
+
+ try {
+ const userFound = await user.findOneByUsername(context.params.username);
+
+ secureUserFound = authorization.filterOutput(userTryingToGet, 'read:user', userFound);
+
+ results = await content.findWithStrategy({
+ strategy: 'new',
+ where: {
+ owner_id: secureUserFound.id,
+ status: 'published',
+ $not_null: ['parent_id'],
+ },
+ page: context.params.page,
+ per_page: context.params.per_page,
+ });
+ } catch (error) {
+ if (error instanceof NotFoundError) {
+ return {
+ notFound: true,
+ revalidate: 1,
+ };
+ }
+
+ throw error;
+ }
+
+ const contentListFound = results.rows;
+
+ const secureContentListFound = authorization.filterOutput(userTryingToGet, 'read:content:list', contentListFound);
+
+ for (const content of secureContentListFound) {
+ if (content.parent_id) {
+ content.body = removeMarkdown(content.body, { maxLength: 255 });
+ } else {
+ delete content.body;
+ }
+ }
+
+ return {
+ props: {
+ contentListFound: JSON.parse(JSON.stringify(secureContentListFound)),
+ pagination: results.pagination,
+ username: secureUserFound.username,
+ },
+
+ revalidate: 10,
+ };
+});
diff --git a/pages/interface/components/TabNewsUI/index.js b/pages/interface/components/TabNewsUI/index.js
index 402b29200..dc236b645 100644
--- a/pages/interface/components/TabNewsUI/index.js
+++ b/pages/interface/components/TabNewsUI/index.js
@@ -20,6 +20,7 @@ export { default as TabCoinButtons } from '@/TabCoinButtons';
export { default as TabCoinCount } from '@/TabCoinCount';
export { default as ThemeProvider } from '@/ThemeProvider';
export { default as ThemeSelector, ThemeSwitcher } from '@/ThemeSelector';
+export { default as UserHeader } from '@/UserHeader';
export {
ActionList,
ActionMenu,
@@ -29,6 +30,7 @@ export {
BranchName,
Button,
Checkbox,
+ CounterLabel,
Flash,
FormControl,
Heading,
@@ -44,6 +46,7 @@ export {
SSRProvider,
SegmentedControl,
Spinner,
+ TabNav,
Text,
TextInput,
Tooltip,
diff --git a/pages/interface/components/UserHeader/index.js b/pages/interface/components/UserHeader/index.js
new file mode 100644
index 000000000..98e6bf267
--- /dev/null
+++ b/pages/interface/components/UserHeader/index.js
@@ -0,0 +1,38 @@
+import { useRouter } from 'next/router';
+
+import { Box, CounterLabel, Link, Pagehead, TabNav, Text } from '@/TabNewsUI';
+
+export default function UserHeader({ username, conteudosCount, respostasCount }) {
+ const router = useRouter();
+
+ return (
+ <>
+
+
+
+ {username}
+
+
+
+
+
+
+ Perfil
+
+
+
+ Publicações {!!conteudosCount && {conteudosCount}}
+
+
+ Respostas {!!respostasCount && {respostasCount}}
+
+
+ >
+ );
+}