Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In-app navigation accessibility #30

Merged
merged 2 commits into from
Feb 2, 2025
Merged
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
2 changes: 1 addition & 1 deletion src/components/layout/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,4 @@ const SideBar = ({ onSearchClick }: SideBarProps) => {
);
};

export default SideBar;
export default SideBar;
26 changes: 0 additions & 26 deletions src/components/profile/Highlights.tsx

This file was deleted.

11 changes: 6 additions & 5 deletions src/components/profile/ProfileInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Link } from 'react-router-dom';
import { followUser, unfollowUser } from '../../api/follow';
import { myProfile } from '../../api/profile';
import { LoginContext } from '../../App';
import ProfileStoryView from './ProfileStoryView';

type ProfileInfoProps = {
userId: number;
Expand Down Expand Up @@ -69,12 +70,12 @@ const ProfileInfo = ({
return (
<div className="mb-8">
<div className="flex items-center mb-4">
<img
src={`https://waffle-instaclone.kro.kr/${profileImage}`}
alt={username}
className="w-20 h-20 rounded-full mr-4"
<ProfileStoryView
userId={userId}
username={username}
profileImage={profileImage}
/>
<div className="flex-1">
<div className="flex-1 ml-4">
<div className="flex items-center mb-2">
<h1 className="text-xl font-semibold mr-4">{username}</h1>
{username === context?.myProfile?.username ? (
Expand Down
78 changes: 78 additions & 0 deletions src/components/profile/ProfileStoryView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';

import type { Story } from '../../types/story';

interface ProfileStoryViewProps {
userId: number;
username: string;
profileImage: string;
}

const ProfileStoryView = ({
userId,
username,
profileImage,
}: ProfileStoryViewProps) => {
const [stories, setStories] = useState<Story[]>([]);
const [loading, setLoading] = useState(true);
const navigate = useNavigate();

useEffect(() => {
const fetchStories = async () => {
try {
const response = await fetch(
`https://waffle-instaclone.kro.kr/api/story/list/${userId}`,
{
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token') ?? ''}`,
},
},
);
if (!response.ok) throw new Error('Failed to fetch stories');
const data = (await response.json()) as Story[];
setStories(data);
} catch (error) {
console.error('Error fetching stories:', error);
} finally {
setLoading(false);
}
};

void fetchStories();
}, [userId]);

const handleClick = () => {
const firstStory = stories[0];
if (stories.length > 0 && firstStory != null) {
void navigate(`/stories/${username}/${firstStory.story_id}`);
}
};

return (
<button onClick={handleClick} className="relative w-20 h-20 rounded-full">
<div
className={`w-full h-full rounded-full p-0.5 ${
stories.length > 0
? 'bg-gradient-to-tr from-yellow-400 to-pink-600'
: 'bg-gray-200'
}`}
>
<div className="w-full h-full rounded-full bg-white p-0.5">
<img
src={`https://waffle-instaclone.kro.kr/${profileImage}`}
alt={username}
className="w-full h-full rounded-full object-cover"
/>
</div>
</div>
{loading && (
<div className="absolute inset-0 flex items-center justify-center bg-black bg-opacity-20 rounded-full">
<div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
</div>
)}
</button>
);
};

export default ProfileStoryView;
5 changes: 3 additions & 2 deletions src/components/shared/PostGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ interface PostGridProps {
}

const PostGrid = ({ posts }: PostGridProps) => {
const sortedPosts = [...posts].sort((a, b) =>
new Date(b.creation_date).getTime() - new Date(a.creation_date).getTime()
const sortedPosts = [...posts].sort(
(a, b) =>
new Date(b.creation_date).getTime() - new Date(a.creation_date).getTime(),
);

return (
Expand Down
27 changes: 20 additions & 7 deletions src/components/story/StoryViewer/StoryUserInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import { useNavigate } from 'react-router-dom';

interface StoryUserInfoProps {
username: string;
profileImage?: string;
creationDate: string;
}

const formatTimeAgo = (dateString: string): string => {
const date = new Date(dateString + 'Z');
const now = new Date();
Expand All @@ -17,17 +25,17 @@ const formatTimeAgo = (dateString: string): string => {
}
};

interface StoryUserInfoProps {
username: string;
profileImage?: string;
creationDate: string;
}

const StoryUserInfo = ({
username,
profileImage,
creationDate,
}: StoryUserInfoProps) => {
const navigate = useNavigate();
const handleUsernameClick = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
void navigate(`/${username}`);
};
return (
<div className="absolute top-2 left-0 right-0 z-20">
<div className="flex items-center space-x-3 px-4 py-2">
Expand All @@ -43,7 +51,12 @@ const StoryUserInfo = ({
/>
</div>
<div className="flex items-center space-x-2">
<span className="text-white font-semibold text-sm">{username}</span>
<button
onClick={handleUsernameClick}
className="text-white font-semibold text-sm hover:underline focus:outline-none"
>
{username}
</button>
<span className="text-gray-300 text-xs">
{formatTimeAgo(creationDate)}
</span>
Expand Down
3 changes: 1 addition & 2 deletions src/pages/ProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import MobileBar from '../components/layout/MobileBar';
import MobileHeader from '../components/layout/MobileHeader';
import SideBar from '../components/layout/SideBar';
import SearchModal from '../components/modals/SearchModal';
import Highlights from '../components/profile/Highlights';
// import Highlights from '../components/profile/Highlights';
import ProfileInfo from '../components/profile/ProfileInfo';
import ProfileTabs from '../components/profile/ProfileTabs';
import { useSearch } from '../hooks/useSearch';
Expand Down Expand Up @@ -77,7 +77,6 @@ const ProfilePage = () => {
fullName={userProfile.full_name}
bio={userProfile.introduce}
/>
<Highlights />
<ProfileTabs postIds={userProfile.post_ids} />
</div>
</div>
Expand Down