Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 0 additions & 23 deletions client/src/@types/api/Category/index.d.ts

This file was deleted.

21 changes: 21 additions & 0 deletions client/src/@types/api/Tag/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface TagResponseData {
type: 'tag_detail',
attributes: {
_id: string,
name: string,
total_title: number,
popularity_ratio: number,
created_at: string,
updated_at: string
}
}

export interface TrendingTagsResponseData {
_id: string,
name: string,
total_title: number,
popularity_ratio: number,
created_at: string,
updated_at: string
}

3 changes: 1 addition & 2 deletions client/src/@types/api/Title/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ export interface TitleResponseData {
name: string,
slug: string,
entry_count: number,
category_id: string,
category_ancestors: string[],
tags: string[],
opened_by: string,
rate: {
username: string,
Expand Down
2 changes: 1 addition & 1 deletion client/src/@types/api/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from './Title'
export * from './Category'
export * from './Tag'
export * from './Entry'
export * from './Message'
export * from './User'
17 changes: 0 additions & 17 deletions client/src/@types/components/CategorySelect/index.d.ts

This file was deleted.

6 changes: 6 additions & 0 deletions client/src/@types/components/TagSearchingBlock/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface TagSearchingBlockProps {
tagFilter: string[]
setTagFilter: (tag: string) => void
beforeTagDeSelect: () => void
updateTagFilterList: React.Dispatch<React.SetStateAction<string>>
}
1 change: 0 additions & 1 deletion client/src/@types/components/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from './Aggrements'
export * from './CategorySelect'
export * from './ImageUpload'
export * from './PageHelmet'
export * from './SignModal'
1 change: 0 additions & 1 deletion client/src/@types/initializations/[entry]/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { TitleResponseData, EntryResponseData } from '@/@types/api'

export interface EntryPageInitials {
title: TitleResponseData,
categoryName: string,
averageTitleRate: number,
entryData: EntryResponseData,
}
3 changes: 1 addition & 2 deletions client/src/@types/initializations/[feed]/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// Local files
import { TitleResponseData, CategoryResponseData } from '@/@types/api'
import { TitleResponseData } from '@/@types/api'
import { EntryAttributes } from '@/@types/pages'

export interface FeedPageInitials {
titleData: TitleResponseData,
categoryData: CategoryResponseData,
featuredEntry: string,
averageTitleRate: number,
entryList: {
Expand Down
4 changes: 2 additions & 2 deletions client/src/@types/initializations/feeds/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Local files
import { TrendingCategoriesResponseData } from '@/@types/api'
import { TrendingTagsResponseData } from '@/@types/api'

export interface FeedsPageInitials {
trendingCategories: TrendingCategoriesResponseData[]
trendingTags: TrendingTagsResponseData[]
}
3 changes: 1 addition & 2 deletions client/src/@types/pages/[feed]/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Local files
import { CategoryResponseData, TitleResponseData, EntryResponseData} from '@/@types/api'
import { TitleResponseData, EntryResponseData} from '@/@types/api'

export interface EntryAttributes {
id: string,
Expand All @@ -17,7 +17,6 @@ export interface EntryAttributes {

export interface FeedHeaderProps {
accessToken: string,
categoryData: CategoryResponseData,
titleData: TitleResponseData,
averageTitleRate: number,
userRole: number,
Expand Down
4 changes: 2 additions & 2 deletions client/src/@types/pages/create-feed/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ export interface CreateTitleFormData {
name: string,
imageBase64: string,
imageFile: string,
categoryId: string,
tags: string,
}

export interface Step1Props {
stepMovementTo: (_step?: string | undefined) => void,
setCreateTitleFormData: React.Dispatch<CreateTitleFormData>,
setReadableCategoryValue: React.Dispatch<React.SetStateAction<ReactNode>>
setReadableTagValue: React.Dispatch<React.SetStateAction<ReactNode>>
}

export interface Step2Props {
Expand Down
6 changes: 3 additions & 3 deletions client/src/@types/pages/feeds/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export interface FeedList {
name: string,
slug: string,
href: string,
categoryName: string,
tags: string[],
entryCount: number,
featuredEntry: {
id: string,
Expand All @@ -21,6 +21,6 @@ export interface FeedList {
export interface FlowHeaderProps {
sortBy: "top" | "hot" | undefined,
setSortBy: (val: "top" | "hot" | undefined) => void,
resetCategoryFilter: () => void,
openFilterModal: () => void
resetTagFilter: () => void,
beforeFilterReset: () => void
}
79 changes: 58 additions & 21 deletions client/src/pages/[feed]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Antd dependencies
import { Modal, Form, Input, Button, Popconfirm, message } from 'antd'
import { Modal, Form, Input, Button, Popconfirm, message, Select, Typography } from 'antd'
import { InfoCircleOutlined } from '@ant-design/icons'

// Other dependencies
Expand All @@ -9,16 +9,16 @@ import { useRouter, NextRouter } from 'next/router'
import { NextPage } from 'next'

// Local files
import { fetchEntriesByTitleId, getAverageTitleRate, updateTitle, deleteTitleImage, updateTitleImage } from '@/services/api'
import { TitleResponseData, CategoryResponseData } from '@/@types/api'
import { API_URL, Guest } from '@/../config/constants'
import { CategorySelect } from '@/components/global/CategorySelect'
import { fetchEntriesByTitleId, getAverageTitleRate, updateTitle, deleteTitleImage, updateTitleImage, searchTagByName } from '@/services/api'
import { TitleResponseData } from '@/@types/api'
import { API_URL } from '@/../config/constants'
import { PageHelmet } from '@/components/global/PageHelmet'
import { EntryAttributes } from '@/@types/pages'
import { getFeedPageInitialValues } from '@/services/initializations'
import { FeedPageInitials } from '@/@types/initializations'
import { ImageUpload } from '@/components/global/ImageUpload'
import { AppLayout } from '@/layouts/AppLayout'
import { Roles } from '@/enums'
import NotFoundPage from '@/pages/404'
import FeedHeader from '@/components/pages/[feed]/FeedHeader'
import FeedEntries from '@/components/pages/[feed]/FeedEntries'
Expand All @@ -29,12 +29,10 @@ const Feed: NextPage<FeedPageInitials> = (props): JSX.Element => {
const globalState = useSelector((state: any) => state.global)
const userRole = useSelector((state: any) => state.user?.attributes.user.role)

const [title, setTitle]: any = useState<TitleResponseData>(props.titleData)
const [category, setCategory]: any = useState<CategoryResponseData>(props.categoryData)
const [title, setTitle] = useState<TitleResponseData>(props.titleData)
const [featuredEntry, setFeaturedEntry] = useState<string>(props.featuredEntry)
const [keywords, setKeywords] = useState(props.keywords)
const [averageTitleRate, setAverageTitleRate] = useState<number | null>(props.averageTitleRate)
const [updateCategoryId, setUpdateCategoryId] = useState<string | string[] | null>(null)
const [entryList, setEntryList] = useState<{
entries: EntryAttributes[],
count: number
Expand All @@ -44,24 +42,56 @@ const Feed: NextPage<FeedPageInitials> = (props): JSX.Element => {
const [titleImageBlob, setTitleImageBlob] = useState<Blob | null>(null)
const [titleNotFound, setTitleNotFound] = useState(props.error)

const [tagResult, setTagResult] = useState([])
const [noTagDataMessage, setNoTagDataMessage] = useState('Enter at least 3 characters to search')
const [tagValue, setTagValue] = useState(title.attributes.tags)

const [form] = Form.useForm()

useEffect(() => {
if (title) handleEntryFetching(10 * (Number(router.query.page) - 1) || 0)
}, [title, sortEntriesBy])

const handleEntryFetching = (page: number): void => {
fetchEntriesByTitleId(title.attributes.id, page, sortEntriesBy).then(async ({ data }) => setEntryList(data.attributes))
}

useEffect(() => {
if (title) handleEntryFetching(10 * (Number(router.query.page) - 1) || 0)
}, [title, sortEntriesBy])
const handleTagSearching = (value: string): void => {
if (value.length < 3) {
setTagResult([])
setNoTagDataMessage('Enter at least 3 characters to search')
}

else {
searchTagByName(value).then(({ data }) => {
const result = []
data.attributes.tags.map(tag => {
result.push(<Select.Option key={tag._id} value={tag.name}>{tag.name}</Select.Option>)
})

if (result.length !== 0) setTagResult(result)
else setTagResult([<Select.Option key={value} value={value}>{value}</Select.Option>])
})
}
}

const handleTagSelect = (value: string): void => {
setTagValue([...tagValue, value])
}

const handleDeSelect = (tag: string) => {
const updatedList = tagValue.filter(value => value !== tag)
setTagValue(updatedList)
}

const getTitleRate = async (titleId: string): Promise<void> => {
await getAverageTitleRate(titleId).then(res => setAverageTitleRate(res.data.attributes.rate || 0))
}

const handleTitleUpdate = async (values: { name: string }): Promise<void> => {
const updatePayload = {
categoryId: updateCategoryId,
name: values.name
name: values.name,
tags: tagValue,
}

if (!titleImageBlob) {
Expand All @@ -85,10 +115,10 @@ const Feed: NextPage<FeedPageInitials> = (props): JSX.Element => {
}

if (titleNotFound) return <NotFoundPage />
if (!entryList || !title || !category || (!averageTitleRate && averageTitleRate !== 0)) return <PageLoading />
if (!entryList || !title || (!averageTitleRate && averageTitleRate !== 0)) return <PageLoading />

return (
<AppLayout authority={Guest}>
<AppLayout authority={Roles.Guest}>
<PageHelmet
title={title.attributes.name}
description={`Best reviews, comments, feedbacks about ${title.attributes.name} around the world`}
Expand All @@ -103,7 +133,6 @@ const Feed: NextPage<FeedPageInitials> = (props): JSX.Element => {
openUpdateModal={(): void => setUpdateModalVisibility(true)}
userRole={userRole}
titleData={title}
categoryData={category}
averageTitleRate={averageTitleRate}
refreshTitleRate={getTitleRate}
/>
Expand Down Expand Up @@ -147,12 +176,20 @@ const Feed: NextPage<FeedPageInitials> = (props): JSX.Element => {
</div>
</div>
<Form.Item style={{ marginBottom: 10 }}>
<CategorySelect
<Select
mode="multiple"
defaultValue={title.attributes.tags}
style={{ width: '100%' }}
defaultValue={category.name}
placeHolder="Electronic"
onSelect={(id): void => setUpdateCategoryId(id)}
/>
placeholder="please specify feed-related keywords"
onSearch={handleTagSearching}
onSelect={handleTagSelect}
onDeselect={handleDeSelect}
notFoundContent={
<Typography.Text style={{ width: '100%' }}> {noTagDataMessage} </Typography.Text>
}
>
{tagResult}
</Select>
</Form.Item>
<Form.Item
name="name"
Expand Down
16 changes: 8 additions & 8 deletions client/src/pages/create-feed/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ import { AxiosError, AxiosResponse } from 'axios'
import { createTitle, createEntry, rateTitle } from '@/services/api'
import { CreateTitleFormData } from '@/@types/pages'
import { StepProvider } from '@/services/step.context.service'
import { User } from '@/../config/constants'
import { AppLayout } from '@/layouts/AppLayout'
import Step1 from '@/components/pages/create-feed/Step1'
import Step2 from '@/components/pages/create-feed/Step2'
import Step3 from '@/components/pages/create-feed/Step3'
import '@/styles/pages/create-feed/style.less'
import './style.less'
import { Roles } from '@/enums'

const CreateFeed: React.FC = () => {
const accessToken = useSelector((state: any) => state.global.accessToken)

const [currentStep, setCurrentStep] = useState<number>(0)
const [stepComponent, setStepComponent] = useState<React.ReactNode>(null)
const [isRequestReady, setIsRequestReady] = useState(false)
const [readableCategoryValue, setReadableCategoryValue] = useState(undefined)
const [readableTagValue, setReadableTagValue] = useState(undefined)
const [firstEntryForm, setFirstEntryForm] = useState<{ text: string } | { text: any }>({
text: undefined
})
Expand All @@ -32,7 +32,7 @@ const CreateFeed: React.FC = () => {
name: undefined,
imageBase64: undefined,
imageFile: undefined,
categoryId: undefined,
tags: undefined,
})

const [feedCreatedSuccessfully, setFeedCreatedSuccessfully] = useState<boolean | null>(null)
Expand All @@ -43,7 +43,7 @@ const CreateFeed: React.FC = () => {
const titleFormData = new FormData()

titleFormData.append('name', createTitleFormData.name)
titleFormData.append('categoryId', createTitleFormData.categoryId)
titleFormData.append('tags', createTitleFormData.tags)
if (createTitleFormData.imageFile) titleFormData.append('image', createTitleFormData.imageFile)

createTitle(titleFormData, accessToken).then(async (res: AxiosResponse) => {
Expand Down Expand Up @@ -106,7 +106,7 @@ const CreateFeed: React.FC = () => {
<Step1
stepMovementTo={handleStepMovement}
setCreateTitleFormData={setCreateTitleFormData}
setReadableCategoryValue={setReadableCategoryValue}
setReadableTagValue={setReadableTagValue}
/>
}
}
Expand All @@ -115,8 +115,8 @@ const CreateFeed: React.FC = () => {
if (!stepComponent) handleStepMovement()

return (
<AppLayout authority={User}>
<StepProvider value={{ createTitleFormData, readableCategoryValue, firstEntryForm, titleRate }}>
<AppLayout authority={Roles.User}>
<StepProvider value={{ createTitleFormData, readableTagValue, firstEntryForm, titleRate }}>
<Card bordered={false}>
<Steps current={currentStep} className={'steps'}>
<Steps.Step title="Create Title" />
Expand Down
Loading