Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/npm_and_yarn/typescript-eslint/es…
Browse files Browse the repository at this point in the history
…lint-plugin-6.18.0
  • Loading branch information
kgilles authored Jan 9, 2024
2 parents 8486794 + 800dd32 commit 3050c57
Show file tree
Hide file tree
Showing 8 changed files with 262 additions and 26 deletions.
22 changes: 11 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
17 changes: 7 additions & 10 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div>
<PostFeed data={postsRes.posts} />
<Feed posts={posts} />
</div>
);
};

export default Feed;
export default page;
8 changes: 7 additions & 1 deletion src/components/TailwindMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 15 additions & 3 deletions src/components/button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,28 @@ interface ButtonProps {
type: 'button' | 'submit' | 'reset';
id?: string;
ariaLabel?: string;
active?: boolean;
className?: string;
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => 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
<button type={type} aria-label={ariaLabel} id={id} onClick={onClick} className={cx('bg-brand dark:bg-brand-dark hover:bg-opacity-90 rounded-md px-23 py-12', className)}>{children}</button>
<button
// eslint-disable-next-line react/button-has-type
type={type}
aria-label={ariaLabel}
id={id}
onClick={onClick}
className={cx('bg-brand dark:bg-brand-dark hover:bg-opacity-90 rounded-md px-23 py-12', {
'bg-blue-300 dark:bg-blue-500': active,
'bg-gray-200 dark:bg-gray-400': !active
}, className)}
>
{children}
</button>
);

export default Button;
52 changes: 52 additions & 0 deletions src/components/front-page-feed/index.tsx
Original file line number Diff line number Diff line change
@@ -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<GetPostsResponse>(posts);

// @todo: Set this to the users default feed type
const [postFeedType, setPostFeedType] = useState<ListingType>();
const [postFeedSort, setPostFeedSort] = useState<SortType>();

// @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 (
<div>
<div className="mb-16 ml-4">
<PostFeedOptions
currentType={postFeedType}
onSortChange={setPostFeedSort}
onTypeChange={setPostFeedType}
currentSort={postFeedSort}
/>
</div>
<PostFeed data={postFeed.posts} />
</div>
);
};

export default Feed;
136 changes: 136 additions & 0 deletions src/components/post-feed-sort/index.tsx
Original file line number Diff line number Diff line change
@@ -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) => (
<ButtonGroup className="flex">
<Button id="post-feed-type-all" type="button" active={currentType === 'All'} onClick={() => onTypeChange('All')} className={buttonGroupClass}>All</Button>
<Button id="post-feed-type-local" type="button" active={currentType === 'Local'} onClick={() => onTypeChange('Local')} className={buttonGroupClass}>Local</Button>
<Button id="post-feed-type-modview" type="button" active={currentType === 'ModeratorView'} onClick={() => onTypeChange('ModeratorView')} className={buttonGroupClass}>Moderator View</Button>
<Button id="post-feed-type-subscribed" type="button" active={currentType === 'Subscribed'} onClick={() => onTypeChange('Subscribed')} className={buttonGroupClass}>Subscribed</Button>
</ButtonGroup>
);

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) => (
<Select value={currentSort} aria-label="Sort Select" className="h-full rounded-md bg-gray-200 dark:bg-gray-400 pl-4" onChange={newValue => onTypeChange(newValue.currentTarget.value as SortType)}>
{sortOptions.map(({ label, value }) => (
<Option key={value} value={value}>{label}</Option>
))}
</Select>
);

interface PostFeedOptionProps {
currentType?: ListingType
onTypeChange: (type: ListingType) => void
currentSort?: SortType
onSortChange: (type: SortType) => void
}

const PostFeedOptions = ({
currentType, onTypeChange, currentSort, onSortChange
}: PostFeedOptionProps) => (
<div className="flex flex-col md:flex-row mt-8 md:mt-0">
<PostFeedType currentType={currentType} onTypeChange={onTypeChange} />
<div className="ml-0 md:ml-4 mt-8 md:mt-0 w-full md:w-auto">
<PostFeedSort currentSort={currentSort} onSortChange={onSortChange} />
</div>
</div>
);

export default PostFeedOptions;
export { PostFeedType, PostFeedSort };
33 changes: 33 additions & 0 deletions src/components/select/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use client';

import React from 'react';
import cx from 'classnames';

interface SortProps {
className?: string;
value?: string;
onChange?: (e: React.ChangeEvent<HTMLSelectElement>) => void;
children: React.ReactNode;
}

const Select = ({
className, value, onChange, children
}: SortProps) => (
<select onChange={onChange} value={value} className={cx('h-full rounded-md bg-gray-200 dark:bg-gray-400 pl-4', className)}>
{children}
</select>
);

interface OptionProps {
value?: string;
children: React.ReactNode;
}

const Option = ({ children, value }: OptionProps) => (
<option value={value}>
{children}
</option>
);

export default Select;
export { Option };

0 comments on commit 3050c57

Please sign in to comment.