Skip to content

Commit

Permalink
유저 정보 조회 기능 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
ipcgrdn committed Nov 19, 2024
1 parent 8f42f71 commit ae6c1c3
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 33 deletions.
39 changes: 21 additions & 18 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Toaster } from "@/components/ui/sonner";
import { ThemeProvider } from "@/components/ui/theme-provider";

import AuthProvider from "@/provider/authProvider";
import { UserProvider } from "@/provider/userProvider";

export const metadata: Metadata = {
title: "Untitled",
Expand Down Expand Up @@ -38,26 +39,28 @@ export default function RootLayout({
disableTransitionOnChange
>
<AuthProvider accessToken={accessToken}>
<ModalProvider />
<Toaster />

<div className="relative flex h-full flex-col overflow-hidden bg-[url('/images/background-color.svg')] bg-cover bg-center dark:bg-[url('/images/background-color-dark.svg')]">
<div className="md:hidden fixed bottom-0 inset-x-0 flex mb-1">
<Bar />
</div>
<div className="hidden md:flex fixed left-0 top-1/2 transform -translate-y-1/2 ml-4">
<Bar />
</div>

<div className="fixed top-0 left-0 right-0">
<Topbar />
</div>

{children}
</div>
<UserProvider>
<ModalProvider />
<Toaster />

<div className="relative flex h-full flex-col overflow-hidden bg-[url('/images/background-color.svg')] bg-cover bg-center dark:bg-[url('/images/background-color-dark.svg')]">
<div className="md:hidden fixed bottom-0 inset-x-0 flex mb-1">
<Bar />
</div>
<div className="hidden md:flex fixed left-0 top-1/2 transform -translate-y-1/2 ml-4">
<Bar />
</div>

<div className="fixed top-0 left-0 right-0">
<Topbar />
</div>

{children}
</div>
</UserProvider>
</AuthProvider>
</ThemeProvider>
</body>
</html>
);
}
}
10 changes: 7 additions & 3 deletions src/app/user/[userId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import { useState } from "react";
import { ChevronDown } from "lucide-react";

import {
IconLink,
Expand All @@ -21,12 +22,15 @@ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import UserTrack from "@/features/user/user-track";
import UserAlbum from "@/features/user/user-album";
import UserPlaylist from "@/features/user/user-playlist";
import { ChevronDown } from "lucide-react";

import { useUser } from "@/provider/userProvider";

export default function UserPage() {
const [activeTab, setActiveTab] = useState("track");
const [array, setArray] = useState("new");

const { user } = useUser();

const tabs = [
{ id: "track", label: "트랙", icon: IconMusic, onClick: () => {} },
{ id: "album", label: "앨범", icon: IconDisc, onClick: () => {} },
Expand All @@ -45,12 +49,12 @@ export default function UserPage() {
<div className="flex h-full w-full gap-x-8 items-center">
<div className="flex flex-col">
<Avatar className="md:w-48 md:h-48 min-w-32 max-w-48 min-h-32 max-h-48">
<AvatarImage src="/images/music1.png" alt="profile" />
<AvatarImage src={user?.artistImage} alt={user?.name} />
<AvatarFallback>U</AvatarFallback>
</Avatar>
</div>
<div className="flex flex-col items-center justify-between gap-y-2 md:gap-y-4 md:py-6">
<div className="md:text-3xl font-bold text-2xl">YANG RARO</div>
<div className="md:text-3xl font-bold text-2xl">{user?.name || "U"}</div>
<div className="flex gap-x-4">
<button className="bg-white text-black hover:bg-black/10 dark:hover:bg-white/75 shadow-lg w-auto font-medium text-sm p-2 rounded-lg">
1.5M
Expand Down
26 changes: 18 additions & 8 deletions src/features/main/bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import useNotiModal from "@/hooks/modal/use-noti-modal";
import useSearchInput from "@/hooks/modal/use-search-input";
import useSigninModal from "@/hooks/modal/use-signin-modal";

import useUploadMenu from "@/hooks/modal/use-upload-menu";
import useSettingMenu from "@/hooks/modal/use-setting-menu";
Expand All @@ -15,29 +16,31 @@ import {
IconHeart,
IconMenu2,
IconSearch,
IconUserCircle,
} from "@tabler/icons-react";

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";

import Image from "next/image";
import { useRouter } from "next/navigation";
import { useMediaQuery } from "react-responsive";
import { useEffect, useRef, useState } from "react";

import { useAuth } from "@/provider/authProvider";
import useSigninModal from "@/hooks/modal/use-signin-modal";
import { useUser } from "@/provider/userProvider";

export function Bar() {
const router = useRouter();
const isLargeScreen = useMediaQuery({ query: "(min-width: 768px)" });

const { isLoggedIn } = useAuth();
const { user } = useUser();

const searchInput = useSearchInput();
const notiModal = useNotiModal();
const signinModal = useSigninModal();
const mobileUploadMenu = useUploadMenu();
const mobileSettingMenu = useSettingMenu();

const { isLoggedIn } = useAuth();

const [uploadOpen, setUploadOpen] = useState(false);
const [settingOpen, setSettingOpen] = useState(false);

Expand Down Expand Up @@ -65,11 +68,13 @@ export function Bar() {
},
{
title: "업로드",
icon: <IconCirclePlus className="h-full w-full text-neutral-500 dark:text-neutral-300" />,
icon: (
<IconCirclePlus className="h-full w-full text-neutral-500 dark:text-neutral-300" />
),
onClick: () => {
if (!isLoggedIn) {
signinModal.onOpen();
} else if (isLargeScreen){
} else if (isLargeScreen) {
setUploadOpen(!uploadOpen);
} else {
mobileUploadMenu.onOpen();
Expand All @@ -92,13 +97,18 @@ export function Bar() {
{
title: "프로필",
icon: (
<IconUserCircle className="h-full w-full text-neutral-500 dark:text-neutral-300" />
<Avatar>
<AvatarImage src={user?.artistImage} alt={user?.name} />
<AvatarFallback>
{user?.name ? user.name.charAt(0).toUpperCase() : "U"}
</AvatarFallback>
</Avatar>
),
onClick: () => {
if (!isLoggedIn) {
signinModal.onOpen();
} else {
router.push("/user/123")
router.push("/user/123");
}
},
},
Expand Down
6 changes: 5 additions & 1 deletion src/features/main/main-album.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"use client";

import SquareContainer from "@/components/container/square-container";
import { useUser } from "@/provider/userProvider";
import { useRouter } from "next/navigation";

const MainAlbum = () => {
const router = useRouter();
const { user } = useUser();

const dummy = [
{
Expand Down Expand Up @@ -76,7 +78,9 @@ const MainAlbum = () => {
return (
<div className="flex flex-col gap-y-2">
<div className="flex justify-start">
<p className="text-[#FF4D74] font-bold text-xl">RARO</p>
<p className="text-[#FF4D74] font-bold text-xl">
{user?.name || "U"}
</p>
<p className="font-bold text-xl">님을 위한 앨범</p>
</div>
<div className="w-full overflow-x-auto flex gap-x-4">
Expand Down
6 changes: 5 additions & 1 deletion src/features/main/main-artist.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"use client";

import SquareContainer from "@/components/container/square-container";
import { useUser } from "@/provider/userProvider";
import { useRouter } from "next/navigation";

const MainArtist = () => {
const router = useRouter();
const { user } = useUser();

const dummy = [
{
Expand Down Expand Up @@ -36,7 +38,9 @@ const MainArtist = () => {
return (
<div className="flex flex-col gap-y-2">
<div className="flex justify-start">
<p className="text-[#FF4D74] font-bold text-xl">RARO</p>
<p className="text-[#FF4D74] font-bold text-xl">
{user?.name || "U"}
</p>
<p className="font-bold text-xl">님을 위한 아티스트</p>
</div>
<div className="w-full overflow-x-auto flex gap-x-4">
Expand Down
6 changes: 5 additions & 1 deletion src/features/main/main-playlist.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"use client";

import SquareContainer from "@/components/container/square-container";
import { useUser } from "@/provider/userProvider";
import { useRouter } from "next/navigation";

const MainPlaylist = () => {
const router = useRouter();
const { user } = useUser();

const dummy = [
{
Expand Down Expand Up @@ -60,7 +62,9 @@ const MainPlaylist = () => {
return (
<div className="flex flex-col gap-y-2">
<div className="flex justify-start">
<p className="text-[#FF4D74] font-bold text-xl">RARO</p>
<p className="text-[#FF4D74] font-bold text-xl">
{user?.name || "U"}
</p>
<p className="font-bold text-xl">님을 위한 플레이리스트</p>
</div>
<div className="w-full overflow-x-auto flex gap-x-4">
Expand Down
3 changes: 3 additions & 0 deletions src/features/main/main-track.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
'use client'

import SquareContainer from "@/components/container/square-container";
import { useUser } from "@/provider/userProvider";
import { useRouter } from "next/navigation";


const MainTrack = () => {
const router = useRouter();
const { user } = useUser();

const dummy = [
{
Expand Down
2 changes: 1 addition & 1 deletion src/features/main/topbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function Topbar() {
)}
>
<span className="text-center text-base font-bold tracking-wide">
START!
로그인
</span>
</button>
</div>
Expand Down
8 changes: 8 additions & 0 deletions src/lib/axios.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import axios from 'axios';

export const api = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_BASE_URL || '',
headers: {
'Content-Type': 'application/json',
},
});
64 changes: 64 additions & 0 deletions src/provider/userProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"use client";

import { AxiosError } from "axios";
import React, { createContext, useContext, useEffect, useState } from "react";

import { api } from "../lib/axios";

export interface Artist {
uuid: string;
name: string;
email: string;
artistImage: string;
}

interface UserContextType {
user: Artist | null;
isLoading: boolean;
error: Error | null;
}

const UserContext = createContext<UserContextType | undefined>(undefined);

export function UserProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<Artist | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);

useEffect(() => {
const fetchUser = async () => {
try {
const { data } = await api.get<Artist>("/artist");
setUser(data);
} catch (err) {
if (err instanceof AxiosError) {
setError(
new Error(
err.response?.data?.message || "Failed to fetch user data"
)
);
} else {
setError(new Error("An unexpected error occurred"));
}
} finally {
setIsLoading(false);
}
};

fetchUser();
}, []);

return (
<UserContext.Provider value={{ user, isLoading, error }}>
{children}
</UserContext.Provider>
);
}

export function useUser() {
const context = useContext(UserContext);
if (context === undefined) {
throw new Error("useUser must be used within a UserProvider");
}
return context;
}

0 comments on commit ae6c1c3

Please sign in to comment.