diff --git a/package-lock.json b/package-lock.json index 2fe1a7e..272029e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "sublinks-js-client": "^0.0.3" }, "devDependencies": { - "@stylistic/eslint-plugin-js": "^1.5.1", + "@stylistic/eslint-plugin-js": "^1.5.3", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", @@ -569,12 +569,12 @@ "dev": true }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.1.tgz", - "integrity": "sha512-iZF0rF+uOhAmOJYOJx1Yvmm3CZ1uz9n0SRd9dpBYHA3QAvfABUORh9LADWwZCigjHJkp2QbCZelGFJGwGz7Siw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.3.tgz", + "integrity": "sha512-XlKnm82fD7Sw9kQ6FFigE0tobvptNBXZWsdfoKmUyK7bNxHsAHOFT8zJGY3j3MjZ0Fe7rLTu86hX/vOl0bRRdQ==", "dev": true, "dependencies": { - "acorn": "^8.11.2", + "acorn": "^8.11.3", "escape-string-regexp": "^4.0.0", "eslint-visitor-keys": "^3.4.3", "espree": "^9.6.1" @@ -1199,9 +1199,9 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -5508,9 +5508,9 @@ } }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", "dev": true, "funding": [ { diff --git a/package.json b/package.json index b89acc7..f47b451 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "sublinks-js-client": "^0.0.3" }, "devDependencies": { - "@stylistic/eslint-plugin-js": "^1.5.1", + "@stylistic/eslint-plugin-js": "^1.5.3", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", diff --git a/src/app/page.tsx b/src/app/page.tsx index 5b9c156..219b5e6 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,24 +1,21 @@ import React from 'react'; -import PostFeed from '@/components/post-feed'; import sublinksClient from '@/utils/client'; -import { PostView } from 'sublinks-js-client'; +import { GetPostsResponse } from 'sublinks-js-client'; +import Feed from '@/components/front-page-feed'; import * as testData from '../../test-data.json'; -const Feed = async () => { +const page = async () => { // @todo: Allow test data when in non-docker dev env // as Sublinks Core doesn't yet handle all post features - const postsRes = process.env.SUBLINKS_API_BASE_URL ? await sublinksClient().getPosts({ - type_: 'All', - sort: 'Active' - }) : testData as unknown as { posts: PostView[] }; - + const posts = process.env.SUBLINKS_API_BASE_URL ? await sublinksClient().getPosts() + : JSON.stringify(testData) as unknown as GetPostsResponse; return (
- +
); }; -export default Feed; +export default page; diff --git a/src/components/TailwindMaterial.ts b/src/components/TailwindMaterial.ts index 55fd636..0e686b8 100644 --- a/src/components/TailwindMaterial.ts +++ b/src/components/TailwindMaterial.ts @@ -8,11 +8,17 @@ import { TabsBody, Tab, TabPanel, - Switch + Switch, + ButtonGroup, + Select, + Option } from '@material-tailwind/react'; export { ThemeProvider, + ButtonGroup, + Select, + Option, Button, Tabs, TabsHeader, diff --git a/src/components/button/index.tsx b/src/components/button/index.tsx index 0a2250e..61da04d 100644 --- a/src/components/button/index.tsx +++ b/src/components/button/index.tsx @@ -6,16 +6,28 @@ interface ButtonProps { type: 'button' | 'submit' | 'reset'; id?: string; ariaLabel?: string; + active?: boolean; className?: string; onClick?: (e: React.MouseEvent) => void; } const Button = ({ - ariaLabel, children, className, id, type, onClick + ariaLabel, children, className, id, type, active, onClick }: ButtonProps) => ( // Rule doesn't like type being a variable even though types force it to be a valid option - // eslint-disable-next-line react/button-has-type - + ); export default Button; diff --git a/src/components/front-page-feed/index.tsx b/src/components/front-page-feed/index.tsx new file mode 100644 index 0000000..c2c98d0 --- /dev/null +++ b/src/components/front-page-feed/index.tsx @@ -0,0 +1,52 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; + +import PostFeed from '@/components/post-feed'; +import sublinksClient from '@/utils/client'; + +import { + GetPostsResponse, ListingType, SortType +} from 'sublinks-js-client'; +import PostFeedOptions from '@/components/post-feed-sort'; +import * as testData from '../../../test-data.json'; + +interface FeedProps { + posts: GetPostsResponse +} + +const Feed = ({ posts }: FeedProps) => { + const [postFeed, setPostFeed] = useState(posts); + + // @todo: Set this to the users default feed type + const [postFeedType, setPostFeedType] = useState(); + const [postFeedSort, setPostFeedSort] = useState(); + + // @todo: Allow test data when in non-docker dev env + // as Sublinks Core doesn't yet handle all post features + useEffect(() => { + async function getPosts() { + setPostFeed(process.env.SUBLINKS_API_BASE_URL ? await sublinksClient().getPosts({ + type_: postFeedType, + sort: postFeedSort + }) : testData as unknown as GetPostsResponse); + } + getPosts(); + }, [postFeedSort, postFeedType]); + + return ( +
+
+ +
+ +
+ ); +}; + +export default Feed; diff --git a/src/components/post-feed-sort/index.tsx b/src/components/post-feed-sort/index.tsx new file mode 100644 index 0000000..79e021a --- /dev/null +++ b/src/components/post-feed-sort/index.tsx @@ -0,0 +1,136 @@ +'use client'; + +import { ListingType, SortType } from 'sublinks-js-client'; +import React from 'react'; +import { ButtonGroup } from '../TailwindMaterial'; +import Button from '../button'; +import Select, { Option } from '../select'; + +interface PostFeedTypeProps { + currentType?: ListingType + onTypeChange: (type: ListingType) => void +} + +const buttonGroupClass = 'px-12 py-4'; + +const PostFeedType = ({ currentType, onTypeChange }: PostFeedTypeProps) => ( + + + + + + +); + +const sortOptions: { label: string, value: string }[] = [ + { + label: 'Active', + value: 'Active' + }, + { + label: 'Hot', + value: 'Hot' + }, + { + label: 'New', + value: 'New' + }, + { + label: 'Old', + value: 'Old' + }, + { + label: 'Top Hour', + value: 'TopHour' + }, + { + label: 'Top Six Hour', + value: 'TopSixHour' + }, + { + label: 'Top Twelve Hour', + value: 'TopTwelveHour' + }, + { + label: 'Top Day', + value: 'TopDay' + }, + { + label: 'Top Week', + value: 'TopWeek' + }, + { + label: 'Top Month', + value: 'TopMonth' + }, + { + label: 'Top Three Months', + value: 'TopThreeMonths' + }, + { + label: 'Top Six Months', + value: 'TopSixMonths' + }, + { + label: 'Top Nine Months', + value: 'TopNineMonths' + }, + { + label: 'Top Year', + value: 'TopYear' + }, + { + label: 'Top All', + value: 'TopAll' + }, + { + label: 'Most Comments', + value: 'MostComments' + }, + { + label: 'New Comments', + value: 'NewComments' + }, + { + label: 'Controversial', + value: 'Controversial' + }, + { + label: 'Scaled', + value: 'Scaled' + } +]; + +interface PostFeedSortProps { + currentSort?: SortType + onSortChange: (type: SortType) => void +} + +const PostFeedSort = ({ currentSort, onSortChange: onTypeChange }: PostFeedSortProps) => ( + +); + +interface PostFeedOptionProps { + currentType?: ListingType + onTypeChange: (type: ListingType) => void + currentSort?: SortType + onSortChange: (type: SortType) => void +} + +const PostFeedOptions = ({ + currentType, onTypeChange, currentSort, onSortChange +}: PostFeedOptionProps) => ( +
+ +
+ +
+
+); + +export default PostFeedOptions; +export { PostFeedType, PostFeedSort }; diff --git a/src/components/select/index.tsx b/src/components/select/index.tsx new file mode 100644 index 0000000..7502d65 --- /dev/null +++ b/src/components/select/index.tsx @@ -0,0 +1,33 @@ +'use client'; + +import React from 'react'; +import cx from 'classnames'; + +interface SortProps { + className?: string; + value?: string; + onChange?: (e: React.ChangeEvent) => void; + children: React.ReactNode; +} + +const Select = ({ + className, value, onChange, children +}: SortProps) => ( + +); + +interface OptionProps { + value?: string; + children: React.ReactNode; +} + +const Option = ({ children, value }: OptionProps) => ( + +); + +export default Select; +export { Option };