mirror of
https://github.com/aljazceru/landscape-template.git
synced 2026-01-31 12:14:30 +01:00
feat: comment card component, update post comments api fields
This commit is contained in:
@@ -72,8 +72,10 @@ export interface NexusGenObjects {
|
||||
PostComment: { // root type
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
body: string; // String!
|
||||
date: string; // String!
|
||||
created_at: string; // String!
|
||||
id: number; // Int!
|
||||
parentId: number; // Int!
|
||||
votes_count: number; // Int!
|
||||
}
|
||||
Project: { // root type
|
||||
cover_image: string; // String!
|
||||
@@ -195,8 +197,10 @@ export interface NexusGenFieldTypes {
|
||||
PostComment: { // field return type
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
body: string; // String!
|
||||
date: string; // String!
|
||||
created_at: string; // String!
|
||||
id: number; // Int!
|
||||
parentId: number; // Int!
|
||||
votes_count: number; // Int!
|
||||
}
|
||||
Project: { // field return type
|
||||
awards: NexusGenRootTypes['Award'][]; // [Award!]!
|
||||
@@ -335,8 +339,10 @@ export interface NexusGenFieldTypeNames {
|
||||
PostComment: { // field return type name
|
||||
author: 'User'
|
||||
body: 'String'
|
||||
date: 'String'
|
||||
created_at: 'String'
|
||||
id: 'Int'
|
||||
parentId: 'Int'
|
||||
votes_count: 'Int'
|
||||
}
|
||||
Project: { // field return type name
|
||||
awards: 'Award'
|
||||
|
||||
@@ -78,8 +78,10 @@ interface PostBase {
|
||||
type PostComment {
|
||||
author: User!
|
||||
body: String!
|
||||
date: String!
|
||||
created_at: String!
|
||||
id: Int!
|
||||
parentId: Int!
|
||||
votes_count: Int!
|
||||
}
|
||||
|
||||
type Project {
|
||||
|
||||
@@ -102,11 +102,13 @@ const PostComment = objectType({
|
||||
name: 'PostComment',
|
||||
definition(t) {
|
||||
t.nonNull.int('id');
|
||||
t.nonNull.string('date');
|
||||
t.nonNull.string('created_at');
|
||||
t.nonNull.string('body');
|
||||
t.nonNull.field('author', {
|
||||
type: "User"
|
||||
});
|
||||
t.nonNull.int('parentId');
|
||||
t.nonNull.int('votes_count');
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import { MOCK_DATA } from 'src/mocks/data';
|
||||
|
||||
import CommentCard from './CommentCard';
|
||||
|
||||
export default {
|
||||
title: 'Posts/Components/CommentCard',
|
||||
component: CommentCard,
|
||||
argTypes: {
|
||||
backgroundColor: { control: 'color' },
|
||||
},
|
||||
} as ComponentMeta<typeof CommentCard>;
|
||||
|
||||
|
||||
const Template: ComponentStory<typeof CommentCard> = (args) => <div className="max-w-[70ch]"><CommentCard {...args} ></CommentCard></div>
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
comment: MOCK_DATA.posts.stories[0].comments[0]
|
||||
}
|
||||
|
||||
|
||||
32
src/features/Posts/Components/CommentCard/CommentCard.tsx
Normal file
32
src/features/Posts/Components/CommentCard/CommentCard.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { BiComment } from "react-icons/bi";
|
||||
import Button from "src/Components/Button/Button";
|
||||
import VotesCount from "src/Components/VotesCount/VotesCount";
|
||||
import { Author } from "../../types"
|
||||
import Header from "../PostCard/Header/Header";
|
||||
|
||||
interface Comment {
|
||||
author: Author
|
||||
created_at: string
|
||||
body: string;
|
||||
votes_count: number
|
||||
}
|
||||
interface Props {
|
||||
comment: Comment
|
||||
}
|
||||
|
||||
export default function CommentCard({ comment }: Props) {
|
||||
return (
|
||||
<div className="border rounded-12 p-24">
|
||||
<Header author={comment.author} date={comment.created_at} />
|
||||
<p className="text-body4 mt-16">
|
||||
{comment.body}
|
||||
</p>
|
||||
<div className="flex gap-24 mt-16 items-center">
|
||||
<VotesCount count={comment.votes_count} />
|
||||
<button className="text-gray-600 font-medium hover:bg-gray-100 py-8 px-12 rounded-8">
|
||||
<BiComment /> <span className="align-middle text-body5">Reply</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -30,16 +30,22 @@ export default function Header({
|
||||
showTimeAgo = true,
|
||||
...props }: Props) {
|
||||
|
||||
const passedTime = dayjs().diff(props.date, 'hour');
|
||||
const dateToShow = passedTime < 24 ?
|
||||
`${dayjs().diff(props.date, 'hour')}h ago`
|
||||
:
|
||||
dayjs(props.date).format('MMMM DD');
|
||||
|
||||
return (
|
||||
<div className='flex gap-8'>
|
||||
<Avatar width={avatarSize[size]} src={props.author.image} />
|
||||
<div>
|
||||
<p className={`${nameSize[size]} text-black font-medium`}>{props.author.name}</p>
|
||||
<p className={`text-body6 text-gray-600`}>{dayjs(props.date).format('MMMM DD')}</p>
|
||||
<p className={`text-body6 text-gray-600`}>{dateToShow}</p>
|
||||
</div>
|
||||
{showTimeAgo && <p className={`${nameSize[size]} text-gray-500 ml-auto `}>
|
||||
{/* {showTimeAgo && <p className={`${nameSize[size]} text-gray-500 ml-auto `}>
|
||||
{dayjs().diff(props.date, 'hour') < 24 ? `${dayjs().diff(props.date, 'hour')}h ago` : undefined}
|
||||
</p>}
|
||||
</p>} */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import Header from "../Header/Header"
|
||||
import { FiUsers } from "react-icons/fi"
|
||||
import Badge from "src/Components/Badge/Badge"
|
||||
import { Link } from "react-router-dom"
|
||||
import { trimText } from "src/utils/helperFunctions"
|
||||
|
||||
export type QuestionCardType = Pick<Question,
|
||||
| 'id'
|
||||
@@ -15,8 +16,14 @@ export type QuestionCardType = Pick<Question,
|
||||
| 'votes_count'
|
||||
| "tags"
|
||||
| "answers_count"
|
||||
| "comments"
|
||||
>;
|
||||
> & {
|
||||
comments: Array<Pick<Question['comments'][number],
|
||||
| 'id'
|
||||
| 'author'
|
||||
| 'body'
|
||||
| 'created_at'
|
||||
>>
|
||||
};
|
||||
interface Props {
|
||||
question: QuestionCardType
|
||||
}
|
||||
@@ -52,9 +59,9 @@ export default function QuestionCard({ question }: Props) {
|
||||
|
||||
<div className="flex p-16 mt-16 flex-col gap-10 bg-gray-50">
|
||||
<div className="flex flex-col gap-10">
|
||||
{question.comments.map(comment => <div key={comment.id} className="border-b last-of-type:border-b-0 pb-8 " >
|
||||
<Header author={comment.author} size='sm' date={comment.date} />
|
||||
<p className="text-body5 text-gray-600 mt-8">{comment.body}</p>
|
||||
{question.comments.slice(0, 2).map(comment => <div key={comment.id} className="border-b last-of-type:border-b-0 pb-8 " >
|
||||
<Header author={comment.author} size='sm' date={comment.created_at} />
|
||||
<p className="text-body5 text-gray-600 mt-8">{trimText(comment.body, 80)}</p>
|
||||
</div>)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ query Feed($take: Int, $skip: Int, $sortBy: String, $category: String) {
|
||||
answers_count
|
||||
comments {
|
||||
id
|
||||
date
|
||||
created_at
|
||||
body
|
||||
author {
|
||||
id
|
||||
|
||||
@@ -20,7 +20,7 @@ query PostDetails($id: Int!, $type: POST_TYPE!) {
|
||||
comments_count
|
||||
comments {
|
||||
id
|
||||
date
|
||||
created_at
|
||||
body
|
||||
author {
|
||||
id
|
||||
@@ -79,7 +79,7 @@ query PostDetails($id: Int!, $type: POST_TYPE!) {
|
||||
answers_count
|
||||
comments {
|
||||
id
|
||||
date
|
||||
created_at
|
||||
body
|
||||
author {
|
||||
id
|
||||
|
||||
@@ -5,7 +5,7 @@ export type InputMaybe<T> = Maybe<T>;
|
||||
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
||||
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
|
||||
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
|
||||
const defaultOptions = {}
|
||||
const defaultOptions = {} as const;
|
||||
/** All built-in and custom scalars, mapped to their actual values */
|
||||
export type Scalars = {
|
||||
ID: string;
|
||||
@@ -110,8 +110,10 @@ export type PostComment = {
|
||||
__typename?: 'PostComment';
|
||||
author: User;
|
||||
body: Scalars['String'];
|
||||
date: Scalars['String'];
|
||||
created_at: Scalars['String'];
|
||||
id: Scalars['Int'];
|
||||
parentId: Scalars['Int'];
|
||||
votes_count: Scalars['Int'];
|
||||
};
|
||||
|
||||
export type Project = {
|
||||
@@ -265,7 +267,7 @@ export type Vote = {
|
||||
export type NavCategoriesQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type NavCategoriesQuery = { __typename?: 'Query', allCategories: Array<{ __typename?: 'Category', id: number, title: string, icon: string | null | undefined, votes_sum: number }> };
|
||||
export type NavCategoriesQuery = { __typename?: 'Query', allCategories: Array<{ __typename?: 'Category', id: number, title: string, icon: string | null, votes_sum: number }> };
|
||||
|
||||
export type SearchProjectsQueryVariables = Exact<{
|
||||
search: Scalars['String'];
|
||||
@@ -287,7 +289,7 @@ export type FeedQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type FeedQuery = { __typename?: 'Query', getFeed: Array<{ __typename?: 'Bounty', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | { __typename?: 'Question', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, answers_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, date: string, body: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } | { __typename?: 'Story', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, comments_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> }> };
|
||||
export type FeedQuery = { __typename?: 'Query', getFeed: Array<{ __typename?: 'Bounty', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | { __typename?: 'Question', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, answers_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, created_at: string, body: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } | { __typename?: 'Story', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, comments_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> }> };
|
||||
|
||||
export type PostDetailsQueryVariables = Exact<{
|
||||
id: Scalars['Int'];
|
||||
@@ -295,14 +297,14 @@ export type PostDetailsQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type PostDetailsQuery = { __typename?: 'Query', getPostById: { __typename?: 'Bounty', id: number, title: string, date: string, body: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, applications: Array<{ __typename?: 'BountyApplication', id: number, date: string, workplan: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } | { __typename?: 'Question', id: number, title: string, date: string, body: string, votes_count: number, type: string, answers_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, date: string, body: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } | { __typename?: 'Story', id: number, title: string, date: string, body: string, votes_count: number, type: string, cover_image: string, comments_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, date: string, body: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } };
|
||||
export type PostDetailsQuery = { __typename?: 'Query', getPostById: { __typename?: 'Bounty', id: number, title: string, date: string, body: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, applications: Array<{ __typename?: 'BountyApplication', id: number, date: string, workplan: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } | { __typename?: 'Question', id: number, title: string, date: string, body: string, votes_count: number, type: string, answers_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, created_at: string, body: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } | { __typename?: 'Story', id: number, title: string, date: string, body: string, votes_count: number, type: string, cover_image: string, comments_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, created_at: string, body: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } };
|
||||
|
||||
export type CategoryPageQueryVariables = Exact<{
|
||||
categoryId: Scalars['Int'];
|
||||
}>;
|
||||
|
||||
|
||||
export type CategoryPageQuery = { __typename?: 'Query', projectsByCategory: Array<{ __typename?: 'Project', id: number, thumbnail_image: string, title: string, votes_count: number, category: { __typename?: 'Category', title: string, id: number } }>, getCategory: { __typename?: 'Category', id: number, title: string, cover_image: string | null | undefined, apps_count: number } };
|
||||
export type CategoryPageQuery = { __typename?: 'Query', projectsByCategory: Array<{ __typename?: 'Project', id: number, thumbnail_image: string, title: string, votes_count: number, category: { __typename?: 'Category', title: string, id: number } }>, getCategory: { __typename?: 'Category', id: number, title: string, cover_image: string | null, apps_count: number } };
|
||||
|
||||
export type AllCategoriesQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -324,7 +326,7 @@ export type ProjectDetailsQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ProjectDetailsQuery = { __typename?: 'Query', getProject: { __typename?: 'Project', id: number, title: string, description: string, cover_image: string, thumbnail_image: string, screenshots: Array<string>, website: string, lightning_address: string | null | undefined, lnurl_callback_url: string | null | undefined, votes_count: number, category: { __typename?: 'Category', id: number, title: string }, awards: Array<{ __typename?: 'Award', title: string, image: string, url: string, id: number }>, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } };
|
||||
export type ProjectDetailsQuery = { __typename?: 'Query', getProject: { __typename?: 'Project', id: number, title: string, description: string, cover_image: string, thumbnail_image: string, screenshots: Array<string>, website: string, lightning_address: string | null, lnurl_callback_url: string | null, votes_count: number, category: { __typename?: 'Category', id: number, title: string }, awards: Array<{ __typename?: 'Award', title: string, image: string, url: string, id: number }>, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } };
|
||||
|
||||
export type VoteMutationVariables = Exact<{
|
||||
projectId: Scalars['Int'];
|
||||
@@ -540,7 +542,7 @@ export const FeedDocument = gql`
|
||||
answers_count
|
||||
comments {
|
||||
id
|
||||
date
|
||||
created_at
|
||||
body
|
||||
author {
|
||||
id
|
||||
@@ -606,7 +608,7 @@ export const PostDetailsDocument = gql`
|
||||
comments_count
|
||||
comments {
|
||||
id
|
||||
date
|
||||
created_at
|
||||
body
|
||||
author {
|
||||
id
|
||||
@@ -665,7 +667,7 @@ export const PostDetailsDocument = gql`
|
||||
answers_count
|
||||
comments {
|
||||
id
|
||||
date
|
||||
created_at
|
||||
body
|
||||
author {
|
||||
id
|
||||
|
||||
@@ -1,32 +1,45 @@
|
||||
|
||||
import dayjs from "dayjs";
|
||||
import { Bounty, Post, Question, Story } from "src/features/Posts/types";
|
||||
import { randomItem } from "src/utils/helperFunctions";
|
||||
import { random, randomItem } from "src/utils/helperFunctions";
|
||||
import { getAvatarImage, getCoverImage } from "./utils";
|
||||
import chance, { Chance } from 'chance'
|
||||
|
||||
const date = dayjs().subtract(5, 'hour').toString();
|
||||
|
||||
import { Chance } from 'chance'
|
||||
|
||||
const getDate = () => dayjs().subtract(random(5, 48), 'hour').toString();
|
||||
|
||||
const getAuthor = () => ({
|
||||
id: 12,
|
||||
name: "John Doe",
|
||||
image: getAvatarImage(),
|
||||
join_date: date
|
||||
join_date: getDate()
|
||||
})
|
||||
|
||||
const getPostComments = (cnt: number = 1): Story['comments'] => Array(cnt).fill(0).map((_, idx) => ({
|
||||
id: idx + 1,
|
||||
body: "This is a comment " + idx + 1,
|
||||
date,
|
||||
author: getAuthor()
|
||||
}))
|
||||
const getPostComments = (cnt: number = 1): Story['comments'] => {
|
||||
|
||||
let comments = [];
|
||||
const rootCommentsIds: any[] = []
|
||||
for (let i = 0; i < cnt; i++) {
|
||||
const parentId = Math.random() < .4 ? 0 : rootCommentsIds.length ? randomItem(...rootCommentsIds) : 0;
|
||||
const comment = {
|
||||
id: i + 1,
|
||||
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nisi, at ut sit id. Vulputate aliquet aliquam penatibus ac, et dictum est etiam. Sagittis odio dui sed viverra donec rutrum iaculis vitae morbi.",
|
||||
created_at: getDate(),
|
||||
author: getAuthor(),
|
||||
votes_count: 123,
|
||||
parentId
|
||||
}
|
||||
comments.push(comment);
|
||||
if (!parentId)
|
||||
rootCommentsIds.push(comment.id);
|
||||
|
||||
}
|
||||
return comments;
|
||||
}
|
||||
|
||||
const getApplications = (cnt: number = 1): Bounty['applications'] => Array(cnt).fill(0).map((_, idx) => ({
|
||||
id: idx + 1,
|
||||
workplan: "I Plan to build this using React, Ts, Redux, and Storybook.",
|
||||
date,
|
||||
date: getDate(),
|
||||
author: getAuthor(),
|
||||
}))
|
||||
|
||||
@@ -72,7 +85,7 @@ export let posts = {
|
||||
body: postBody,
|
||||
cover_image: getCoverImage(),
|
||||
comments_count: 31,
|
||||
date,
|
||||
date: getDate(),
|
||||
votes_count: 120,
|
||||
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
|
||||
type: "Story",
|
||||
@@ -94,7 +107,7 @@ export let posts = {
|
||||
body: postBody,
|
||||
cover_image: getCoverImage(),
|
||||
applicants_count: 31,
|
||||
date,
|
||||
date: getDate(),
|
||||
votes_count: 120,
|
||||
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
|
||||
tags: [
|
||||
@@ -116,7 +129,7 @@ export let posts = {
|
||||
title: 'Digital Editor, Mars Review of Books',
|
||||
body: postBody,
|
||||
answers_count: 31,
|
||||
date,
|
||||
date: getDate(),
|
||||
votes_count: 70,
|
||||
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
|
||||
tags: [
|
||||
@@ -124,20 +137,7 @@ export let posts = {
|
||||
{ id: 2, title: "webln" },
|
||||
],
|
||||
author: getAuthor(),
|
||||
comments: [
|
||||
{
|
||||
id: 1,
|
||||
author: getAuthor(),
|
||||
date,
|
||||
body: 'Naw, I’m 42 and know people who started in their 50’s, you got this!'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
author: getAuthor(),
|
||||
date,
|
||||
body: 'Naw, I’m 42 and know people who started in their 50’s, you got this!'
|
||||
},
|
||||
]
|
||||
comments: getPostComments(3)
|
||||
},
|
||||
] as Question[]
|
||||
}
|
||||
@@ -154,8 +154,11 @@ export const feed: Post[] = Array(30).fill(0).map((_, idx) => {
|
||||
const post = feedRandomer.pickone([posts.bounties[0], posts.questions[0], posts.stories[0]])
|
||||
|
||||
return {
|
||||
...post, id: idx + 1, title: feedRandomer.sentence({
|
||||
...post,
|
||||
id: idx + 1,
|
||||
title: feedRandomer.sentence({
|
||||
words: feedRandomer.integer({ min: 4, max: 7 })
|
||||
})
|
||||
}),
|
||||
date: getDate(),
|
||||
}
|
||||
})
|
||||
|
||||
@@ -52,11 +52,9 @@ export function lazyModal<T extends ComponentType<any>>
|
||||
<C direction={!LoadingComponent && direction} {...props} />
|
||||
</Suspense>
|
||||
|
||||
|
||||
|
||||
// type ThenArg<T> = T extends PromiseLike<infer U> ? U : T
|
||||
// type y = ThenArg<ReturnType<typeof x>>
|
||||
// type yy = ComponentProps<y['default']>
|
||||
|
||||
return { LazyComponent, preload };
|
||||
}
|
||||
|
||||
export function trimText(text: string, length: number) {
|
||||
return text.slice(0, length) + (text.length > length ? "..." : "")
|
||||
}
|
||||
Reference in New Issue
Block a user