Move next js project to archive (#207)

This commit is contained in:
Aaron Po
2026-04-20 02:30:25 -04:00
committed by GitHub
parent 92ec16ce93
commit d47e3ed7f0
347 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
import useFollowStatus from '@/hooks/data-fetching/user-follows/useFollowStatus';
import useGetUsersFollowedByUser from '@/hooks/data-fetching/user-follows/useGetUsersFollowedByUser';
import useGetUsersFollowingUser from '@/hooks/data-fetching/user-follows/useGetUsersFollowingUser';
import { sendUserFollowRequest } from '@/requests/users/auth';
import GetUserSchema from '@/services/users/auth/schema/GetUserSchema';
import { FC, useState } from 'react';
import { FaUserCheck, FaUserPlus } from 'react-icons/fa';
import { z } from 'zod';
interface UserFollowButtonProps {
mutateFollowerCount: ReturnType<typeof useGetUsersFollowingUser>['mutate'];
mutateFollowingCount: ReturnType<typeof useGetUsersFollowedByUser>['mutate'];
user: z.infer<typeof GetUserSchema>;
}
const UserFollowButton: FC<UserFollowButtonProps> = ({
user,
mutateFollowerCount,
mutateFollowingCount,
}) => {
const { isFollowed, mutate: mutateFollowStatus } = useFollowStatus(user.id);
const [isLoading, setIsLoading] = useState(false);
const onClick = async () => {
try {
setIsLoading(true);
await sendUserFollowRequest({ userId: user.id });
await Promise.all([
mutateFollowStatus(),
mutateFollowerCount(),
mutateFollowingCount(),
]);
setIsLoading(false);
} catch (e) {
setIsLoading(false);
}
};
return (
<button
type="button"
className={`btn btn-sm gap-2 rounded-2xl lg:btn-md ${
!isFollowed ? 'btn-ghost outline' : 'btn-primary'
}`}
onClick={() => {
onClick();
}}
disabled={isLoading}
>
{isFollowed ? (
<>
<FaUserCheck className="text-xl" />
Followed
</>
) : (
<>
<FaUserPlus className="text-xl" />
Follow
</>
)}
</button>
);
};
export default UserFollowButton;

View File

@@ -0,0 +1,85 @@
import useTimeDistance from '@/hooks/utilities/useTimeDistance';
import { FC, useContext } from 'react';
import { z } from 'zod';
import { format } from 'date-fns';
import GetUserSchema from '@/services/users/auth/schema/GetUserSchema';
import useGetUsersFollowedByUser from '@/hooks/data-fetching/user-follows/useGetUsersFollowedByUser';
import useGetUsersFollowingUser from '@/hooks/data-fetching/user-follows/useGetUsersFollowingUser';
import UserContext from '@/contexts/UserContext';
import Link from 'next/link';
import UserAvatar from '../Account/UserAvatar';
import UserFollowButton from './UserFollowButton';
interface UserHeaderProps {
user: z.infer<typeof GetUserSchema>;
}
const UserHeader: FC<UserHeaderProps> = ({ user }) => {
const timeDistance = useTimeDistance(new Date(user.createdAt));
const { followingCount, mutate: mutateFollowingCount } = useGetUsersFollowedByUser({
userId: user.id,
pageSize: 10,
});
const { followerCount, mutate: mutateFollowerCount } = useGetUsersFollowingUser({
userId: user.id,
pageSize: 10,
});
const { user: currentUser } = useContext(UserContext);
return (
<header className="card items-center text-center">
<div className="card-body w-full items-center justify-center">
<div className="h-40 w-40">
<UserAvatar user={user} />
</div>
<div>
<h1 className="text-2xl font-bold lg:text-4xl">{user.username}</h1>
<div className="flex space-x-3 text-lg font-bold">
<span>{followingCount} Following</span>
<span>{followerCount} Followers</span>
</div>
</div>
<div>
<span className="italic">
joined{' '}
{timeDistance && (
<span
className="tooltip tooltip-bottom"
data-tip={format(new Date(user.createdAt), 'MM/dd/yyyy')}
>
{`${timeDistance} ago`}
</span>
)}
</span>
</div>
{user.bio && (
<div className="my-2 w-6/12">
<p className="text-sm">{user.bio}</p>
</div>
)}
<div className="my-2 flex items-center justify-center">
{currentUser?.id !== user.id ? (
<UserFollowButton
mutateFollowerCount={mutateFollowerCount}
user={user}
mutateFollowingCount={mutateFollowingCount}
/>
) : (
<Link href={`/users/account/edit-profile`} className="btn btn-primary btn-sm">
Edit Profile
</Link>
)}
</div>
</div>
</header>
);
};
export default UserHeader;