Skip to content

Commit

Permalink
Fix various bugs and implement new features (#52)
Browse files Browse the repository at this point in the history
* Jovells workflow auto sync after pr merge (#4)

* Update main.yml

* Update main.yml

* removed dev admin collection

* prevent protected route redirect whern `user` not ready

* fixed post btn disabling when post type is changed after setting invalid question link

* fixed showing own interaction notifications

* implemented following & isNotFollowing

* implmented posts following tab

* increase size of posts to fetch at a time to 5 and enhance infitite scroll

* Add react-share library for social media sharing

* implemented share button
  • Loading branch information
Jovells authored Dec 23, 2023
1 parent fdc3fd3 commit 2b9ebc4
Show file tree
Hide file tree
Showing 19 changed files with 604 additions and 429 deletions.
2 changes: 1 addition & 1 deletion frontend/nextjs/emt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ import {chain, envChains} from './contracts'


export const USERS_COLLECTION = collection(firestore, 'users');
export const ADMIN_COLLECTION = collection(firestore, 'admin');
export const NOTIFICATIONS_COLLECTION = process.env.NODE_ENV === "production"? collection(firestore, 'notifications') : collection(firestore, 'dev', String(process.env.NEXT_PUBLIC_DEV!) + chain.id , 'notifications');
export const CLAIM_HISTORY_COLLECTION = process.env.NODE_ENV === "production"? collection(firestore, 'claimHistory') : collection(firestore, 'dev', String(process.env.NEXT_PUBLIC_DEV!) + chain.id , 'claimHistory');
export const CONTENTS_COLLECTION = process.env.NODE_ENV === "production"? collection(firestore, 'contents') : collection(firestore, 'dev', String(process.env.NEXT_PUBLIC_DEV!) + chain.id, 'contents');
export const EXPT_LISTINGS_COLLECTION = process.env.NODE_ENV === "production"? collection(firestore, 'exptListings') : collection(firestore, 'dev', String(process.env.NEXT_PUBLIC_DEV!) + chain.id, 'exptListings');
export const BOOKINGS_COLLECTION = process.env.NODE_ENV === "production"? collection(firestore, 'bookings') : collection(firestore, 'dev', String(process.env.NEXT_PUBLIC_DEV!) + chain.id, 'bookings');
export const ADMIN_COLLECTION = process.env.NODE_ENV === "production"? collection(firestore, 'admin') : collection(firestore, 'dev', String(process.env.NEXT_PUBLIC_DEV!) + chain.id, 'admin');

export const exptLevelKeys = [1, 2, 3]
39 changes: 39 additions & 0 deletions frontend/nextjs/package-lock.json

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

1 change: 1 addition & 0 deletions frontend/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"react-hook-form": "^7.48.2",
"react-icons": "^4.11.0",
"react-quill": "^2.0.0",
"react-share": "^5.0.3",
"siwe": "^2.1.4",
"tailwind-merge": "^2.0.0",
"tailwindcss-animate": "^1.0.7",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default function DappProviders({
}: {
children: React.ReactNode
}) {
// TODO: @Jovells persist Signupdata lo loaclstorage
// TODO: @Jovells persist Signupdata lo localstorage

return (
<QueryClientProvider client={queryClient}>
Expand Down
13 changes: 11 additions & 2 deletions frontend/nextjs/src/app/(with wallet)/_components/user-List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,25 @@ import Link from "next/link";
import { PROFILE_PAGE } from "./page-links";
import { HiCheckBadge, HiOutlineFire } from "react-icons/hi2";
import { Badge } from "@/components/ui/badge";
import { useUser } from "@/lib/hooks/user";

export default function UserList({ filters, max = 5 }: { filters?: ProfileFilters, max?: number }) {
const { fetchProfiles} = useBackend();
const {user} = useUser();
if (filters?.isNotFollowing && !user)
return <div className="pl-3">Sign in To get Suggestions</div>

export default function UserList({ filters }: { filters?: ProfileFilters }) {
const { fetchProfiles } = useBackend();
return (
<InfiniteScroll
fetcher={fetchProfiles}
queryKey={["profiles"]}
itemKey={(data: UserProfile) => data.uid}
filters={filters}
noDataMessage="No profiles found. Please try later"
getNextPageParam={(lastPage) => {
if(max && max<= lastPage.length) return undefined
return lastPage[lastPage.length - 1]
}}
ItemComponent={({ data }: { data: UserProfile }) => (
<Link
key={data.uid}
Expand Down
9 changes: 4 additions & 5 deletions frontend/nextjs/src/app/(with wallet)/dapp/p/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import {RichTextDisplayContainer} from '@/components/ui/rich-text-display-contai
import { Badge } from '@/components/ui/badge';
import UserList from '@/app/(with wallet)/_components/user-List';
import Link from 'next/link';
import { PROFILE_PAGE } from '@/app/(with wallet)/_components/page-links';
import { POST_PAGE, PROFILE_PAGE } from '@/app/(with wallet)/_components/page-links';
import ShareButton from '@/components/ui/share-button';


const Post = ({ params }: { params: { slug: string } }) => {
Expand Down Expand Up @@ -140,7 +141,7 @@ const PostTemplate = ({ post, isLoading, isFollowingUser, toggleFollowing }: Pos
</div>
<div className='ml-3'>
<div className="flex items-center">
<Link className='px-0 py-0 text-muted text-sm hover:text-accent-3' href={PROFILE_PAGE(post.author?.uid)}>
<Link className='px-0 py-0 text-muted text-sm hover:text-accent-3' href={PROFILE_PAGE(post.post.owner)}>
{post.author?.displayName}
</Link>
{post.author?.isExpert === true && <HiCheckBadge className="w-4 h-4 ml-1 text-accent-3" />}
Expand Down Expand Up @@ -200,9 +201,7 @@ const PostTemplate = ({ post, isLoading, isFollowingUser, toggleFollowing }: Pos

<Voter post={post} />

<Button variant="ghost" aria-label='Upvote a post' size="icon">
<HiOutlineShare className="h-5 w-5 text-foreground" />
</Button>
<ShareButton title={post.post.title} path={POST_PAGE(post.metadata.id)} />
</CardFooter>
</Card>
</ScrollArea>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ const CreatePostForm = () => {
/>

{/* Only display the post type if you're answering a question */}
{form.watch().postType == POST_TYPE[2] && (
{form.watch().postType == POST_TYPE[2] ? (
<FormField
control={form.control}
name="questionPostURL"
Expand All @@ -163,7 +163,10 @@ const CreatePostForm = () => {
</FormItem>
)}
/>
)}
):(
(form.getFieldState('questionPostURL').isDirty&&form.resetField('questionPostURL')), "")
}


<Separator />

Expand Down Expand Up @@ -274,7 +277,7 @@ const CreatePostForm = () => {
</Button>
<Button
type="submit"
isLoading={isFormLoading}
isLoading={isFormLoading}
loadingText="Creating post"
disabled={isFormLoading || !form.formState.isValid}
variant="gradient"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { useToast } from "@/components/ui/use-toast";
import { toast } from "@/components/ui/use-toast";
import RichTextEditor from "@/components/ui/rich-text-editor";
import Image from "next/image";
import { Textarea } from "@/components/ui/textarea";
Expand All @@ -31,7 +31,6 @@ import { UserProfile } from "@/lib/types";
import PageLoading from "@/components/ui/page-loading";
import NoData from "@/components/ui/no-data";

//TODO: @Jovells FIXME form sometimes doesnt load old values

const formSchema = z.object({
displayName: z
Expand Down Expand Up @@ -89,16 +88,7 @@ const EditProfileForm = () => {
const [selectedTags, setSelectedTags] = useState(profile?.tags || []);
const [isButtonLoading, setButtonLoading] = useState(false)

const { toast } = useToast();

// TODO INFO: @jovells if you want to create a toast with a progress bar, use the snippet below
// toast({
// title: "Profile updated!",
// description: <div>
// <Progress value={43} className="h-2 mt-2 w-full text-accent-4 bg-accent-shade" />
// </div>,
// duration: Infinity
// });


async function onSubmit(values: z.infer<typeof formSchema>) {
setButtonLoading(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ async function validateUpdates(
console.log("validateUpdates function", data);
const validations = {} as userUpdateValidationResult;

//totally prevent updating of email
//TODO: @Jovells IMPLEMENT UPDATE EMAIL FLOW
//this line totally prevents updating of email
data.email && (validations.email = false);

//prevent updating of username to existing username
Expand Down
9 changes: 7 additions & 2 deletions frontend/nextjs/src/components/ui/infinite-scroller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,13 @@ export default function InfiniteScroll({
error,
} = useInfiniteQuery({
queryKey: [...queryKey, size, filters],
queryFn: async ({ pageParam, meta }) => {
queryFn: async ({ pageParam }) => {
filters = filters;
const datas = await fetcher(pageParam, size, filters);
if (filters?.isNotFollowing){
console.log('datapages', datas)
}

return datas;
},
initialPageParam: undefined as any,
Expand Down Expand Up @@ -101,6 +105,7 @@ export default function InfiniteScroll({
return <NoData message={noDataMessage} />;
}


return (
<>
<div {...props}>
Expand All @@ -116,7 +121,7 @@ export default function InfiniteScroll({
})}
</div>

<div ref={ref}>
<div className="-mt-1.5" ref={ref}>
{isFetchingNextPage ? (
noDataComponent ? (
noDataComponent
Expand Down
8 changes: 4 additions & 4 deletions frontend/nextjs/src/components/ui/post-card.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use client';
import React from 'react'
import {
Card,
Expand All @@ -17,6 +18,7 @@ import Voter from '@/components/ui/voter';
import { formatDistance } from 'date-fns';
import { RichTextDisplayContainer } from '@/components/ui/rich-text-display-container';
import { Badge } from './badge';
import ShareButton from './share-button';



Expand All @@ -41,7 +43,7 @@ const PostCard = ({ data }: { data: Content }) => {
</div>
<div className='ml-3'>
<div className="flex items-center">
<Link className='px-0 py-0 text-muted hover:text-accent-3' href={PROFILE_PAGE(author.uid)}>
<Link className='px-0 py-0 text-muted hover:text-accent-3' href={PROFILE_PAGE(post.owner)}>
{author?.displayName}
</Link>
{author?.isExpert === true && <HiCheckBadge className="w-4 h-4 ml-1 text-accent-3" />}
Expand Down Expand Up @@ -92,9 +94,7 @@ const PostCard = ({ data }: { data: Content }) => {
<CardFooter className='pb-0 px-0 flex justify-between'>
<Voter post={data} />

<Button variant="ghost" aria-label='Share post' size="icon">
<HiOutlineShare className="h-5 w-5 text-foreground" />
</Button>
<ShareButton title={post.title} path={POST_PAGE(metadata.id)}></ShareButton>
</CardFooter>
</Card>
)
Expand Down
4 changes: 3 additions & 1 deletion frontend/nextjs/src/components/ui/posts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ import InfiniteScroll from "./infinite-scroller";

type Props = {
filters?: { owner?: string; tags?: string[]; isFollowing?: true };
sizePerFetch?: number;
};

export default function Posts({ filters }: Props) {
export default function Posts({ filters, sizePerFetch }: Props) {
const { fetchPosts } = useBackend();

return (
<InfiniteScroll
itemKey={(data: Content) => data.metadata.id}
size={sizePerFetch || 5}
ItemComponent={(props) => (
<>
<PostCard {...props} />
Expand Down
2 changes: 1 addition & 1 deletion frontend/nextjs/src/components/ui/profile-search-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const ProfileSearchCard = ({ data }: { data: Content }) => {

return (
<Card className='border-none p-4 hover:bg-accent-shade'>
<Link href={PROFILE_PAGE(author.uid)}>
<Link href={PROFILE_PAGE(post.owner)}>

<CardHeader className='px-0 pt-0 pb-0'>
<div className="flex items-center justify-between w-full">
Expand Down
48 changes: 48 additions & 0 deletions frontend/nextjs/src/components/ui/share-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useState } from 'react';
import {Button} from './button';
import {Popover} from './popover';
import {EmailShareButton, FacebookShareButton, TwitterShareButton, LinkedinShareButton, EmailIcon, FacebookIcon, LinkedinIcon, TwitterIcon, XIcon} from 'react-share'
import { toast } from './use-toast';
import { HiOutlineShare } from 'react-icons/hi2';
import { PopoverContent, PopoverTrigger } from '@radix-ui/react-popover';

export default function ShareButton({title, path} : {title: string, path: string}) {
const [isOpen, setIsOpen] = useState(false);

const handleButtonClick = () => {
setIsOpen(!isOpen);
};

const handleCopyLink = () => {
navigator.clipboard.writeText(url);
toast({
title: 'Link copied to clipboard',
variant: 'success',
})
setIsOpen(false);
};
const url = location.origin + path

return (
<div>

<Popover open={isOpen}>
<PopoverTrigger asChild>
<Button onClick={handleButtonClick} variant="ghost" aria-label='Share post' size="icon">
<HiOutlineShare className="h-5 w-5 text-foreground" />
</Button>
</PopoverTrigger>
<PopoverContent onInteractOutside={() => setIsOpen(false)} sideOffset={12} alignOffset={0} align="end" className=" shadow-lg p-2 rounded flex space-x-2 bg-accent-shade">

<LinkedinShareButton title={title} url={url} ><LinkedinIcon size={32} round/></LinkedinShareButton>
<TwitterShareButton title={title} url={url} ><XIcon size={32} round/></TwitterShareButton>
<EmailShareButton subject={title} url={url} ><EmailIcon size={32} round/></EmailShareButton>
<FacebookShareButton title={title} url={url} ><FacebookIcon size={32} round/></FacebookShareButton>
<Button variant={'outline'} size={'sm'} onClick={handleCopyLink}>Copy Link</Button>
</PopoverContent>
</Popover>

</div>
);
};

9 changes: 9 additions & 0 deletions frontend/nextjs/src/components/ui/use-toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ import type {
ToastProps,
} from "@/components/ui/toast"

// INFO: if you want to create a toast with a progress bar, use the snippet below
// toast({
// title: "Profile updated!",
// description: <div>
// <Progress value={43} className="h-2 mt-2 w-full text-accent-4 bg-accent-shade" />
// </div>,
// duration: Infinity
// });

const TOAST_LIMIT = 1
const TOAST_REMOVE_DELAY = 1000000

Expand Down
3 changes: 2 additions & 1 deletion frontend/nextjs/src/components/ui/voter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ export default function Voter({ post }: { post: Content }) {
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) {
const voteType = e.currentTarget.name as "upvote" | "downvote";
console.log('voting', voteType, post )
const res = await mutateAsync({
id: post.metadata.id,
voteType,
owner: post.author?.uid,
owner: post.post.owner,
});
console.log("res", res);
}
Expand Down
Loading

0 comments on commit 2b9ebc4

Please sign in to comment.