mirror of https://github.com/sunface/rust-course
parent
664216ca87
commit
8c2bf9f379
@ -0,0 +1,72 @@
|
||||
import { Text, Box, Heading, Image, Center, Flex, VStack, Divider, useToast } from "@chakra-ui/react"
|
||||
import Card from "components/card"
|
||||
import Sidebar from "layouts/sidebar/sidebar"
|
||||
import React, { useEffect, useState } from "react"
|
||||
import {editorLinks} from "src/data/links"
|
||||
import { requestApi } from "utils/axios/request"
|
||||
import { Story } from "src/types/story"
|
||||
import { useRouter } from "next/router"
|
||||
import PageContainer1 from "layouts/page-container1"
|
||||
import Empty from "components/empty"
|
||||
import TextStoryCard from "components/story/text-story-card"
|
||||
|
||||
const PostsPage = () => {
|
||||
const [posts, setPosts] = useState([])
|
||||
const router = useRouter()
|
||||
const toast = useToast()
|
||||
const getPosts = () => {
|
||||
requestApi.get(`/story/posts/drafts`).then((res) => setPosts(res.data)).catch(_ => setPosts([]))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getPosts()
|
||||
}, [])
|
||||
|
||||
const editPost = (post: Story) => {
|
||||
router.push(`/editor/post/${post.id}`)
|
||||
}
|
||||
|
||||
const onDeletePost= async (id) => {
|
||||
await requestApi.delete(`/story/post/${id}`)
|
||||
getPosts()
|
||||
toast({
|
||||
description: "删除成功",
|
||||
status: "success",
|
||||
duration: 2000,
|
||||
isClosable: true,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageContainer1 >
|
||||
<Box display="flex">
|
||||
<Sidebar routes={editorLinks} title="创作中心"/>
|
||||
<Card ml="4" p="6" width="100%">
|
||||
<Flex alignItems="center" justify="space-between">
|
||||
<Heading size="md">草稿列表({posts.length})</Heading>
|
||||
</Flex>
|
||||
{
|
||||
posts.length === 0 ?
|
||||
<Empty />
|
||||
:
|
||||
<>
|
||||
<VStack mt="4">
|
||||
{posts.map(post =>
|
||||
<Box width="100%" key={post.id}>
|
||||
<TextStoryCard story={post} showActions={true} mt="4" onEdit={() => editPost(post)} onDelete={() => onDeletePost(post.id)} showSource={false}/>
|
||||
<Divider mt="5" />
|
||||
</Box>
|
||||
)}
|
||||
</VStack>
|
||||
<Center><Text layerStyle="textSecondary" fontSize="sm" mt="5">没有更多文章了</Text></Center>
|
||||
</>
|
||||
}
|
||||
</Card>
|
||||
</Box>
|
||||
</PageContainer1>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default PostsPage
|
||||
|
@ -0,0 +1,180 @@
|
||||
import { Menu, MenuButton, MenuList, MenuItem, Text, Box, Heading, Image, HStack, Center, Button, Flex, Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalFooter, FormControl, FormLabel, FormHelperText, Input, FormErrorMessage, VStack, Textarea, Divider, useColorModeValue, useToast } from "@chakra-ui/react"
|
||||
import Card from "components/card"
|
||||
import Sidebar from "layouts/sidebar/sidebar"
|
||||
import React, { useEffect, useState } from "react"
|
||||
import { editorLinks } from "src/data/links"
|
||||
import { requestApi } from "utils/axios/request"
|
||||
import { useDisclosure } from "@chakra-ui/react"
|
||||
import { Field, Form, Formik } from "formik"
|
||||
import { config } from "configs/config"
|
||||
import TextStoryCard from "components/story/text-story-card"
|
||||
import { Story } from "src/types/story"
|
||||
import { FaExternalLinkAlt, FaRegEdit } from "react-icons/fa"
|
||||
import { useRouter } from "next/router"
|
||||
import { ReserveUrls } from "src/data/reserve-urls"
|
||||
import Link from "next/link"
|
||||
import PageContainer1 from "layouts/page-container1"
|
||||
import Empty from "components/empty"
|
||||
import { IDType } from "src/types/id"
|
||||
var validator = require('validator');
|
||||
|
||||
const newSeries: Story = { title: '', brief: '', cover: '',type: IDType.Series }
|
||||
const PostsPage = () => {
|
||||
const [currentSeries, setCurrentSeries] = useState(null)
|
||||
const [posts, setPosts] = useState([])
|
||||
const router = useRouter()
|
||||
const toast = useToast()
|
||||
const getPosts = () => {
|
||||
requestApi.get(`/story/posts/editor?type=${IDType.Series}`).then((res) => setPosts(res.data)).catch(_ => setPosts([]))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getPosts()
|
||||
}, [])
|
||||
|
||||
|
||||
function validateTitle(value) {
|
||||
let error
|
||||
if (!value?.trim()) {
|
||||
error = "标题不能为空"
|
||||
}
|
||||
|
||||
if (value?.length > config.posts.titleMaxLen) {
|
||||
error = "标题长度不能超过128"
|
||||
}
|
||||
|
||||
return error
|
||||
}
|
||||
|
||||
function validateUrl(value) {
|
||||
let error
|
||||
if (value && !validator.isURL(value)) {
|
||||
error = "URL格式不合法"
|
||||
}
|
||||
return error
|
||||
}
|
||||
|
||||
function validateBrief(value) {
|
||||
let error
|
||||
if (value && value.length > config.posts.briefMaxLen) {
|
||||
error = `文本长度不能超过${config.posts.briefMaxLen}`
|
||||
}
|
||||
return error
|
||||
}
|
||||
|
||||
const submitPost = async (values, _) => {
|
||||
await requestApi.post(`/story`, values)
|
||||
toast({
|
||||
description: "提交成功",
|
||||
status: "success",
|
||||
duration: 2000,
|
||||
isClosable: true,
|
||||
})
|
||||
setCurrentSeries(null)
|
||||
getPosts()
|
||||
}
|
||||
|
||||
const editPost = (post: Story) => {
|
||||
if (post.url.trim() === "") {
|
||||
router.push(`/editor/post/${post.id}`)
|
||||
} else {
|
||||
setCurrentSeries(post)
|
||||
}
|
||||
}
|
||||
|
||||
const onDeletePost = async (id) => {
|
||||
await requestApi.delete(`/story/post/${id}`)
|
||||
getPosts()
|
||||
toast({
|
||||
description: "删除成功",
|
||||
status: "success",
|
||||
duration: 2000,
|
||||
isClosable: true,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageContainer1 >
|
||||
<Box display="flex">
|
||||
<Sidebar routes={editorLinks} title="创作中心" />
|
||||
<Card ml="4" p="6" width="100%">
|
||||
{currentSeries ?
|
||||
<Formik
|
||||
initialValues={currentSeries}
|
||||
onSubmit={submitPost}
|
||||
>
|
||||
{(props) => (
|
||||
<Form>
|
||||
<VStack spacing="6">
|
||||
<Field name="title" validate={validateTitle}>
|
||||
{({ field, form }) => (
|
||||
<FormControl isInvalid={form.errors.title && form.touched.title} >
|
||||
<FormLabel>标题</FormLabel>
|
||||
<Input {...field} placeholder="name" />
|
||||
<FormErrorMessage>{form.errors.title}</FormErrorMessage>
|
||||
</FormControl>
|
||||
)}
|
||||
</Field>
|
||||
<Field name="cover" validate={validateUrl}>
|
||||
{({ field, form }) => (
|
||||
<FormControl isInvalid={form.errors.cover && form.touched.cover}>
|
||||
<FormLabel>封面图片</FormLabel>
|
||||
<Input {...field} placeholder="https://..." />
|
||||
<FormErrorMessage>{form.errors.cover}</FormErrorMessage>
|
||||
</FormControl>
|
||||
)}
|
||||
</Field>
|
||||
<Field name="brief" validate={validateBrief}>
|
||||
{({ field, form }) => (
|
||||
<FormControl isInvalid={form.errors.brief && form.touched.brief}>
|
||||
<FormLabel>简介</FormLabel>
|
||||
<Textarea {...field} placeholder="在本系列文章中,我们将..."></Textarea>
|
||||
<FormErrorMessage>{form.errors.brief}</FormErrorMessage>
|
||||
</FormControl>
|
||||
)}
|
||||
</Field>
|
||||
</VStack>
|
||||
<Box mt={6}>
|
||||
<Button
|
||||
colorScheme="teal"
|
||||
variant="outline"
|
||||
type="submit"
|
||||
_focus={null}
|
||||
>
|
||||
提交
|
||||
</Button>
|
||||
<Button variant="ghost" ml="4" _focus={null} onClick={() => setCurrentSeries(null)}>取消</Button>
|
||||
</Box>
|
||||
</Form>
|
||||
)}
|
||||
</Formik> :
|
||||
<>
|
||||
<Flex alignItems="center" justify="space-between">
|
||||
<Heading size="md">系列({posts.length})</Heading>
|
||||
<Button colorScheme="teal" size="sm" onClick={() => setCurrentSeries(newSeries)} _focus={null}>新建系列</Button>
|
||||
</Flex>
|
||||
{
|
||||
posts.length === 0 ? <Empty />
|
||||
:
|
||||
<>
|
||||
<VStack mt="4">
|
||||
{posts.map(post =>
|
||||
<Box width="100%" key={post.id}>
|
||||
<TextStoryCard story={post} showActions={true} mt="4" onEdit={() => editPost(post)} onDelete={() => onDeletePost(post.id)} showSource={false}/>
|
||||
<Divider mt="5" />
|
||||
</Box>
|
||||
)}
|
||||
</VStack>
|
||||
<Center><Text layerStyle="textSecondary" fontSize="sm" mt="5">没有更多文章了</Text></Center>
|
||||
</>
|
||||
}
|
||||
</>}
|
||||
</Card>
|
||||
</Box>
|
||||
</PageContainer1>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default PostsPage
|
||||
|
@ -0,0 +1,79 @@
|
||||
import { Box, Divider, Heading, HStack, Image} from "@chakra-ui/react"
|
||||
import Comments from "components/comments/comments"
|
||||
import { MarkdownRender } from "components/markdown-editor/render"
|
||||
import { StoryAuthor } from "components/story/story-author"
|
||||
import TagTextCard from "components/story/tag-text-card"
|
||||
import SEO from "components/seo"
|
||||
import siteConfig from "configs/site-config"
|
||||
import PostNav from "layouts/nav/post-nav"
|
||||
import PageContainer from "layouts/page-container"
|
||||
import { useRouter } from "next/router"
|
||||
import React, { useEffect, useState } from "react"
|
||||
import { Story } from "src/types/story"
|
||||
import { requestApi } from "utils/axios/request"
|
||||
import StorySidebar from "components/story/story-sidebar"
|
||||
|
||||
const PostPage = () => {
|
||||
const router = useRouter()
|
||||
const id = router.query.id
|
||||
const [post, setPost]: [Story, any] = useState(null)
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
getData()
|
||||
}
|
||||
}, [id])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (router && router.asPath.indexOf("#comments") > -1) {
|
||||
setTimeout(() => {
|
||||
location.href = "#comments"
|
||||
}, 100)
|
||||
}
|
||||
}, [router])
|
||||
|
||||
const getData = async () => {
|
||||
const res = await requestApi.get(`/story/post/${id}`)
|
||||
setPost(res.data)
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<SEO
|
||||
title={siteConfig.seo.title}
|
||||
description={siteConfig.seo.description}
|
||||
/>
|
||||
{post && <PageContainer nav={<PostNav post={post} />} mt="2rem">
|
||||
<>
|
||||
<HStack alignItems="top" spacing={[0, 0, 14, 14]}>
|
||||
<Box width={["100%", "100%", "75%", "75%"]} height="fit-content" pl={[0, 0, "0%", "10%"]}>
|
||||
<Image src={post.cover} />
|
||||
<Box px="2">
|
||||
<Heading size="lg" my="6" lineHeight="1.5">{post.title}</Heading>
|
||||
|
||||
<Divider my="4" />
|
||||
<StoryAuthor story={post} />
|
||||
<Divider my="4" />
|
||||
|
||||
<MarkdownRender md={post.md} py="2" mt="6" />
|
||||
</Box>
|
||||
<HStack ml="2" spacing="3" mt="4">{post.rawTags.map(tag => <TagTextCard key={tag.id} tag={tag} />)}</HStack>
|
||||
|
||||
<Box mt="6" p="2"><Comments storyID={post.id} /></Box>
|
||||
</Box>
|
||||
<Box pt="16">
|
||||
<StorySidebar story={post} />
|
||||
</Box>
|
||||
</HStack>
|
||||
|
||||
</>
|
||||
</PageContainer>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default PostPage
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
import React from "react"
|
||||
import { Box, BoxProps, useColorModeValue } from "@chakra-ui/react"
|
||||
|
||||
export const Card = (props: BoxProps) => {
|
||||
const bg = useColorModeValue("white", "gray.780")
|
||||
return (
|
||||
<Box
|
||||
bg={bg}
|
||||
borderRadius=".5rem"
|
||||
borderWidth="1px"
|
||||
p={[2,2,4,4]}
|
||||
// boxShadow="0 1px 1px 0 rgb(0 0 0 / 5%)"
|
||||
backgroundImage="linear-gradient(45deg, rgb(237, 132, 129) 0%, rgb(51, 128, 236) 100%)"
|
||||
backgroundPosition="initial initial"
|
||||
backgroundRepeat="initial initial"
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Card
|
@ -1,50 +0,0 @@
|
||||
import React from "react"
|
||||
import { Box, chakra, Flex, Heading, HStack, Image, Text, useMediaQuery, VStack } from "@chakra-ui/react"
|
||||
import { Post } from "src/types/posts"
|
||||
import PostAuthor from "./post-author"
|
||||
import Link from "next/link"
|
||||
import UnicornLike from "../interaction/like"
|
||||
import { FaHeart, FaRegBookmark, FaRegComment, FaRegHeart } from "react-icons/fa"
|
||||
import SvgButton from "components/svg-button"
|
||||
import Bookmark from "./bookmark"
|
||||
|
||||
interface Props {
|
||||
post: Post
|
||||
size?: 'md' | 'sm'
|
||||
}
|
||||
|
||||
|
||||
export const SimplePostCard = (props: Props) => {
|
||||
const { post,size='md' } = props
|
||||
const [isLargeScreen] = useMediaQuery("(min-width: 768px)")
|
||||
const Layout = isLargeScreen ? HStack : VStack
|
||||
return (
|
||||
<VStack alignItems="left" spacing="0">
|
||||
<Link href={`/${post.creator.username}/${post.id}`}><Heading pb="2" size="sm" cursor="pointer">{post.title}</Heading></Link>
|
||||
<HStack pl="1" spacing="5" fontSize={size==='md'? '1rem' : ".9rem"}>
|
||||
<Link href={`/${post.creator.username}`}><Text cursor="pointer">{post.creator.nickname}</Text></Link>
|
||||
|
||||
<HStack opacity="0.9">
|
||||
{post.liked ?
|
||||
<Box color="red.400"><FaHeart fontSize="1.1rem" /></Box>
|
||||
:
|
||||
<FaRegHeart fontSize="1.1rem" />}
|
||||
<Text ml="2">{post.likes}</Text>
|
||||
</HStack>
|
||||
|
||||
<Link href={`/${post.creator.username}/${post.id}#comments`}>
|
||||
<HStack opacity="0.9" cursor="pointer">
|
||||
<FaRegComment fontSize="1.1rem" />
|
||||
<Text ml="2">{post.comments}</Text>
|
||||
</HStack>
|
||||
</Link>
|
||||
|
||||
|
||||
|
||||
<Box style={{marginLeft: '4px'}}><Bookmark storyID={post.id} bookmarked={post.bookmarked} height=".95rem"/></Box>
|
||||
</HStack>
|
||||
</VStack>
|
||||
)
|
||||
}
|
||||
|
||||
export default SimplePostCard
|
@ -0,0 +1,48 @@
|
||||
import React from "react"
|
||||
import { Box, Heading, HStack, Text, useMediaQuery, VStack } from "@chakra-ui/react"
|
||||
import { Story } from "src/types/story"
|
||||
import Link from "next/link"
|
||||
import { FaHeart, FaRegComment, FaRegHeart } from "react-icons/fa"
|
||||
import Bookmark from "./bookmark"
|
||||
import { getCommentsUrl, getStoryUrl } from "utils/story"
|
||||
|
||||
interface Props {
|
||||
story: Story
|
||||
size?: 'md' | 'sm'
|
||||
}
|
||||
|
||||
|
||||
export const SimpleStoryCard = (props: Props) => {
|
||||
const { story,size='md' } = props
|
||||
const [isLargeScreen] = useMediaQuery("(min-width: 768px)")
|
||||
const Layout = isLargeScreen ? HStack : VStack
|
||||
return (
|
||||
<VStack alignItems="left" spacing="0">
|
||||
<Link href={getStoryUrl(story)}><Heading pb="2" size="sm" cursor="pointer">{story.title}</Heading></Link>
|
||||
<HStack pl="1" spacing="5" fontSize={size==='md'? '1rem' : ".9rem"}>
|
||||
<Link href={`/${story.creator.username}`}><Text cursor="pointer">{story.creator.nickname}</Text></Link>
|
||||
|
||||
<HStack opacity="0.9">
|
||||
{story.liked ?
|
||||
<Box color="red.400"><FaHeart fontSize="1.1rem" /></Box>
|
||||
:
|
||||
<FaRegHeart fontSize="1.1rem" />}
|
||||
<Text ml="2">{story.likes}</Text>
|
||||
</HStack>
|
||||
|
||||
<a href={`${getCommentsUrl(story)}#comments`}>
|
||||
<HStack opacity="0.9" cursor="pointer">
|
||||
<FaRegComment fontSize="1.1rem" />
|
||||
<Text ml="2">{story.comments}</Text>
|
||||
</HStack>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<Box style={{marginLeft: '4px'}}><Bookmark storyID={story.id} bookmarked={story.bookmarked} height=".95rem"/></Box>
|
||||
</HStack>
|
||||
</VStack>
|
||||
)
|
||||
}
|
||||
|
||||
export default SimpleStoryCard
|
@ -1,65 +1,69 @@
|
||||
import React from "react"
|
||||
import { Box, chakra, Flex, Heading, HStack, Image, Text, useMediaQuery, VStack } from "@chakra-ui/react"
|
||||
import { Post } from "src/types/posts"
|
||||
import PostAuthor from "./post-author"
|
||||
import { Box, Heading, HStack, Image, Text, useMediaQuery, VStack } from "@chakra-ui/react"
|
||||
import { Story } from "src/types/story"
|
||||
import StoryAuthor from "./story-author"
|
||||
import Link from "next/link"
|
||||
import Like from "../interaction/like"
|
||||
import { FaHeart, FaRegHeart } from "react-icons/fa"
|
||||
import Bookmark from "./bookmark"
|
||||
import { getSvgIcon } from "components/svg-icon"
|
||||
import Count from "components/count"
|
||||
import Highlighter from 'react-highlight-words';
|
||||
import { IDType } from "src/types/id"
|
||||
import { ReserveUrls } from "src/data/reserve-urls"
|
||||
import { getCommentsUrl, getStoryUrl } from "utils/story"
|
||||
|
||||
interface Props {
|
||||
post: Post
|
||||
story: Story
|
||||
type?: string
|
||||
highlight?: string
|
||||
}
|
||||
|
||||
|
||||
export const PostCard = (props: Props) => {
|
||||
const { post, type = "classic" } = props
|
||||
export const StoryCard = (props: Props) => {
|
||||
const { story, type = "classic" } = props
|
||||
const [isLargeScreen] = useMediaQuery("(min-width: 768px)")
|
||||
const Layout = isLargeScreen ? HStack : VStack
|
||||
|
||||
|
||||
return (
|
||||
<VStack alignItems="left" spacing={type === "classic" ? 4 : 2} p="2">
|
||||
<PostAuthor post={post} showFooter={false} size="md" />
|
||||
<Link href={`/${post.creator.username}/${post.id}`}>
|
||||
<StoryAuthor story={story} showFooter={false} size="md" />
|
||||
<a href={getStoryUrl(story)} target="_blank">
|
||||
<Layout alignItems={isLargeScreen ? "top" : "left"} cursor="pointer" pl="2" pt="1">
|
||||
<VStack alignItems="left" spacing={type==="classic"? 3 : 2} width={isLargeScreen && type === "classic" ? "calc(100% - 18rem)" : '100%'}>
|
||||
<Heading size="md" fontSize={type==="classic" ? '1.4rem' : '1.2rem'}><Highlighter
|
||||
highlightClassName="highlight-search-match"
|
||||
textToHighlight={post.title}
|
||||
textToHighlight={story.title}
|
||||
searchWords={[props.highlight]}
|
||||
/>
|
||||
</Heading>
|
||||
{type !== "classic" && <HStack>{post.rawTags.map(t => <Text layerStyle="textSecondary" fontSize="md">#{t.name}</Text>)}</HStack>}
|
||||
{type !== "classic" && <HStack>{story.rawTags.map(t => <Text layerStyle="textSecondary" fontSize="md">#{t.name}</Text>)}</HStack>}
|
||||
<Text layerStyle={type === "classic" ? "textSecondary" : null}>
|
||||
<Highlighter
|
||||
highlightClassName="highlight-search-match"
|
||||
textToHighlight={post.brief}
|
||||
textToHighlight={story.brief}
|
||||
searchWords={[props.highlight]}
|
||||
/></Text>
|
||||
</VStack>
|
||||
{post.cover && type === "classic" && <Image src={post.cover} width="18rem" height="120px" pt={isLargeScreen ? 0 : 2} borderRadius="4px" />}
|
||||
{story.cover && type === "classic" && <Image src={story.cover} width="18rem" height="120px" pt={isLargeScreen ? 0 : 2} borderRadius="4px" />}
|
||||
</Layout>
|
||||
</Link>
|
||||
</a>
|
||||
|
||||
<HStack pl="2" spacing="5">
|
||||
<Like storyID={post.id} liked={post.liked} count={post.likes} fontSize="18px" />
|
||||
<Link href={`/${post.creator.username}/${post.id}#comments`}>
|
||||
<Like storyID={story.id} liked={story.liked} count={story.likes} fontSize="18px" />
|
||||
<a href={`${getCommentsUrl(story)}#comments`} target="_blank">
|
||||
<HStack opacity="0.9" cursor="pointer">
|
||||
{getSvgIcon("comments", "1.3rem")}
|
||||
<Text ml="2"><Count count={post.comments} /></Text>
|
||||
<Text ml="2"><Count count={story.comments} /></Text>
|
||||
</HStack>
|
||||
</Link>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<Box style={{ marginLeft: '4px' }}><Bookmark height="1.05rem" storyID={post.id} bookmarked={post.bookmarked} /></Box>
|
||||
<Box style={{ marginLeft: '4px' }}><Bookmark height="1.05rem" storyID={story.id} bookmarked={story.bookmarked} /></Box>
|
||||
</HStack>
|
||||
</VStack>
|
||||
)
|
||||
}
|
||||
|
||||
export default PostCard
|
||||
export default StoryCard
|
@ -0,0 +1,9 @@
|
||||
export enum IDType {
|
||||
Undefined = "0",
|
||||
Tag = "1",
|
||||
Comment = "2",
|
||||
User = "3",
|
||||
Post = "4",
|
||||
Series = "5",
|
||||
Book = "6"
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
import { ReserveUrls } from "src/data/reserve-urls"
|
||||
import { IDType } from "src/types/id"
|
||||
import { Story } from "src/types/story"
|
||||
|
||||
export const getStoryUrl = (story:Story) => {
|
||||
if (story.url) {
|
||||
return story.url
|
||||
}
|
||||
|
||||
if (story.type === IDType.Post) {
|
||||
return `/${story.creator.username}/${story.id}`
|
||||
}
|
||||
|
||||
if (story.type === IDType.Series) {
|
||||
return `${ReserveUrls.Series}/${story.id}`
|
||||
}
|
||||
|
||||
if (story.type === IDType.Book) {
|
||||
return `${ReserveUrls.Books}/${story.id}`
|
||||
}
|
||||
|
||||
return "/"
|
||||
}
|
||||
|
||||
export const getCommentsUrl = (story:Story) => {
|
||||
if (story.type === IDType.Post) {
|
||||
return `/${story.creator.username}/${story.id}`
|
||||
}
|
||||
|
||||
if (story.type === IDType.Series) {
|
||||
return `${ReserveUrls.Series}/${story.id}`
|
||||
}
|
||||
|
||||
if (story.type === IDType.Book) {
|
||||
return `${ReserveUrls.Books}/${story.id}`
|
||||
}
|
||||
|
||||
return "/"
|
||||
}
|
Loading…
Reference in new issue