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

[양정화] sprint9 #288

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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

# production
/build
example.http

# misc
.DS_Store
Expand All @@ -33,3 +34,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# React Component Preview
previewConfig.json
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/pages/api-reference/create-next-app).

## Getting Started

Expand All @@ -18,23 +18,23 @@ Open [http://localhost:3000](http://localhost:3000) with your browser to see the

You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
[API routes](https://nextjs.org/docs/pages/building-your-application/routing/api-routes) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/pages/building-your-application/routing/api-routes) instead of React pages.

This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
This project uses [`next/font`](https://nextjs.org/docs/pages/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
- [Learn Next.js](https://nextjs.org/learn-pages-router) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/pages/building-your-application/deploying) for more details.
114 changes: 114 additions & 0 deletions components/layout/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import styled from 'styled-components';
import { Container } from '../../styles/Common.styles';
import font from '@/styles/fontStyle.styles';
import { media } from '@/styles/media.styles';

const ICON_FACEBOOK = '/ic_facebook.png';
const ICON_INSTAGRAM = '/ic_instagram.png';
const ICON_TWITTER = '/ic_twitter.png';
const ICON_YOUTUBE = '/ic_youtube.png';
import Link from 'next/link';
import IconLink from '../shared/IconLink';

const snsLink = [
{
id: 1,
name: 'facebook',
to: 'https://www.facebook.com/',
src: ICON_FACEBOOK,
},
{ id: 2, name: 'twitter', to: 'https://x.com/', src: ICON_TWITTER },
{
id: 3,
name: 'youtube',
to: 'https://www.youtube.com/',
src: ICON_YOUTUBE,
},
{
id: 4,
name: 'instagram',
to: 'https://www.instagram.com/',
src: ICON_INSTAGRAM,
},
];

function Footer() {
return (
<StyledFooter>
<FooterContainer>
<FooterItem className='text-copyright'>
<p>©codeit - 2024</p>
</FooterItem>
<FooterItem className='link-page'>
<Link href='/privacy'>Privacy Policy</Link>
<Link href='/faq'>FAQ</Link>
</FooterItem>
<FooterItem className='link-sns'>
{snsLink.map((sns) => (
<IconLink key={sns.id} to={sns.to} name={sns.name} src={sns.src} />
))}
</FooterItem>
</FooterContainer>
</StyledFooter>
);
}

export default Footer;

export const StyledFooter = styled.footer`
height: 16rem;
padding-top: 3.2rem;
background-color: var(--gray-900);
`;

export const FooterContainer = styled(Container)`
display: flex;
justify-content: space-between;
${media.mo`
flex-wrap: wrap;
gap: 2.5rem 0;
justify-content: center;
`}
`;

export const FooterItem = styled.div`
${font('16')}
${media.mo`
flex-basis: 100%;
`}
&.text-copyright {
${media.mo`
order: 2;
flex: 1;
`}
p {
color: var(--gray-400);
${media.mo`
color: #676767;
`}
}
}
&.link-page {
display: flex;
gap: 3rem;
${media.mo`
flex: 1;
flex-basis: 50%;
`}
a {
color: var(--gray-200);
${media.mo`
color: #cfcfcf;
`}
}
}
&.link-sns {
display: flex;
gap: 1.2rem;
${media.mo`
flex: 1;
flex-basis: 50%;
justify-content: flex-end;
`}
}
`;
64 changes: 64 additions & 0 deletions components/layout/Headers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useRouter } from 'next/router';
import styled from 'styled-components';
import useDeviceType from '@/utils/deviceType';
import { useAuth } from '@/context/AuthContext';

import { Container } from '@/styles/Common.styles';
import { media } from '@/styles/media.styles';

import Navigation from './Navigation';
import ProfileImage from '../shared/ProfileImage';
import Logo from '../shared/Logo';
import Button from '../shared/Button';

function Headers() {
const router = useRouter();
const deviceType = useDeviceType();
const { hasLogin } = useAuth();

return (
<HeaderContainer>
<StlyedContainer>
<Logo size='sm' />
{router.pathname !== '/' && <Navigation />}
{hasLogin ? (
<>
<ProfileImage />
</>
) : (
<Button
href='/login'
color='blue'
size={deviceType === 'mo' ? 'small' : 'medium'}>
로그인
</Button>
)}
</StlyedContainer>
</HeaderContainer>
);
}

export default Headers;

const HeaderContainer = styled.div`
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 7rem;
border-bottom: 1px solid #dfdfdf;
background-color: #fff;
z-index: 999;
`;

const StlyedContainer = styled(Container)`
display: flex;
justify-content: space-between;
align-items: center;
height: 100%;
gap: 3.2rem;

${media.mo`
gap: 0.8rem;
`}
`;
52 changes: 52 additions & 0 deletions components/layout/Navigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useRouter } from 'next/router';
import Link from 'next/link';
import styled from 'styled-components';

import font from '@/styles/fontStyle.styles';
import { media } from '@/styles/media.styles';

function Navigation() {
const router = useRouter();

const navLinks = [
{ name: '자유게시판', path: '/boards' },
{ name: '중고마켓', path: '/items' },
];

return (
<StyledGnb>
{navLinks.map((link) => {
const isActive = router.pathname === link.path;

return (
<li key={link.name}>
<StyledLink href={link.path} $isActive={isActive} shallow>
{link.name}
</StyledLink>
</li>
);
})}
</StyledGnb>
);
}

export default Navigation;

const StyledGnb = styled.ul`
display: flex;
flex: 1;
`;

const StyledLink = styled(Link)<{ $isActive: boolean }>`
color: ${({ $isActive }) =>
$isActive ? 'var(--blue-100)' : 'var(--gray-600)'};
padding: 2.1rem 1.5rem;
${font('18b')}
text-align: center;
text-decoration: none;

${media.mo`
padding: 2.1rem 0.4rem;
${font('16b')}
`}
`;
93 changes: 93 additions & 0 deletions components/pages/boards/BoardCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import styled from 'styled-components';
import { formatRegistrationDate } from '@/utils/format';

import font from '@/styles/fontStyle.styles';
import { media } from '@/styles/media.styles';

import UserInfo from '@/components/shared/UserInfo';
const IMG_BEST = '/img_badge.svg';

interface Writer {
nickname: string;
}

export interface BoardCardProps {
title: string;
likeCount: number;
updatedAt: string;
image: string;
writer: Writer;
}

function BoardCard({
title = '타이틀',
likeCount = 0,
updatedAt = '',
writer = { nickname: '닉네임' },
image = '',
}: BoardCardProps) {
return (
<BoardCardContainer>
<BoardCardBestBege src={IMG_BEST} alt='Best 뱃지' />
<BoardCardTitleArea>
<h3>{title}</h3>
<BoardCardProdImagesArea>
<img src={image} alt='상품 이미지' />
</BoardCardProdImagesArea>
</BoardCardTitleArea>
<UserInfo wide>
<UserInfo.UserName userName={writer.nickname} />
<UserInfo.Heart count={likeCount} size='sm' wide />
<UserInfo.Date date={formatRegistrationDate(updatedAt)} />
</UserInfo>
</BoardCardContainer>
);
}

const BoardCardContainer = styled.div`
background-color: var(--gray-50);
border-radius: 0.8rem;
padding: 0 2.4rem 1.6rem;
width: 38.4rem;
height: auto;
${media.ta`
width: 34rem;
`}
${media.mo`
width: 34.3rem;
`}
`;

const BoardCardBestBege = styled.img`
width: 10.2rem;
height: 3rem;
margin-bottom: 1.6rem;
`;

const BoardCardTitleArea = styled.div`
display: flex;
gap: 0.8rem;
justify-content: space-between;
margin-bottom: 1.8rem;
${media.tamo`
margin-bottom: 4rem;
gap: 4rem;
`}

h3 {
${font('20sb')}
${media.tamo`
${font('18sb')}
`}
}
`;

export const BoardCardProdImagesArea = styled.div`
width: 7.2rem;
height: 7.2rem;
border-radius: 0.6rem;
overflow: hidden;
border: 1px solid var(--gray-200);
`;

export default BoardCard;
Loading
Loading