Skip to content

Commit

Permalink
feat: Added image onLoad function
Browse files Browse the repository at this point in the history
  • Loading branch information
he2e2 committed Aug 28, 2024
1 parent 940fb06 commit ee0fc08
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 44 deletions.
101 changes: 57 additions & 44 deletions src/app/pages/travel-auto-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,41 @@ import {
ScrollMotion,
TimeCard,
CustomButton,
LoadingCard,
} from '@/components';
import { ChoiceList } from '@/components/travel';
import { Times } from '@/features/travel-schedule/travel-schedule.type';
import { useIntersectionObserver } from '@/shared';

interface Loading {
$isLoading: boolean;
interface Location {
id: number;
imageUrl: string;
name: string;
}

const dummyLocations: Location[] = [
{
id: 1,
imageUrl: 'https://picsum.photos/400/600',
name: 'hi',
},
{
id: 2,
imageUrl: 'https://picsum.photos/2600/2600',
name: 'hi',
},
{
id: 3,
imageUrl: 'https://picsum.photos/200/500',
name: 'hi',
},
{
id: 4,
imageUrl: 'https://picsum.photos/100/100',
name: 'hi',
},
];

export function TravelAutoPage() {
const [searchContent, setSearchContent] = useState('');

Expand All @@ -42,7 +68,7 @@ export function TravelAutoPage() {
choiceList={{
where: searchContent,
what: event,
when: time,
when: time === '기본' ? undefined : time,
}}
/>
),
Expand All @@ -52,7 +78,11 @@ export function TravelAutoPage() {
<InputWhat where={searchContent} setContent={setEvent} />
<InputWhen selectedTime={time} setContent={setTime} />
<div ref={inputWhenRef}>
<Results isLoading={isLoading} />
<Results
isLoading={isLoading}
locations={dummyLocations}
nextLocations={dummyLocations}
/>
</div>
</styles.wrapper>
{!isResultVisible && <ScrollMotion />}
Expand Down Expand Up @@ -126,29 +156,39 @@ function InputWhen({
);
}

function Results({ isLoading }: { isLoading: boolean }) {
function Results({
isLoading,
locations,
nextLocations,
}: {
isLoading: boolean;
locations: Location[];
nextLocations: Location[];
}) {
return (
<styles.container>
<styles.resultCon>
<styles.description>이런 곳 어떠세요?</styles.description>
<styles.cardList>
<styles.card $isLoading={isLoading} />
<styles.card $isLoading={isLoading} />
<styles.card $isLoading={isLoading} />
<styles.card $isLoading={isLoading} />
<styles.card $isLoading={isLoading} />
<styles.card $isLoading={isLoading} />
{locations.map((location) => (
<LoadingCard
key={location.id}
dataLoading={isLoading}
imageUrl={location.imageUrl}
/>
))}
</styles.cardList>
</styles.resultCon>
<styles.resultCon>
<styles.description>이후에 이 곳은 어떠세요?</styles.description>
<styles.cardList>
<styles.card $isLoading={isLoading} />
<styles.card $isLoading={isLoading} />
<styles.card $isLoading={isLoading} />
<styles.card $isLoading={isLoading} />
<styles.card $isLoading={isLoading} />
<styles.card $isLoading={isLoading} />
{nextLocations.map((location) => (
<LoadingCard
key={location.id}
dataLoading={isLoading}
imageUrl={location.imageUrl}
/>
))}
</styles.cardList>
</styles.resultCon>
</styles.container>
Expand Down Expand Up @@ -219,31 +259,4 @@ const styles = {
}
justify-content: flex-start;
`,

card: styled.div<Loading>`
width: 6.875rem;
height: 7.6875rem;
flex-shrink: 0;
border-radius: 14px;
background-color: ${(props) => (props.$isLoading ? '#f9f9f9' : '#fff')};
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0),
rgba(255, 255, 255, 0.5),
rgba(255, 255, 255, 0)
);
background-size: 40px 100%;
background-repeat: no-repeat;
background-position: left -80px top 0;
box-shadow: 2px 3px 4px 0px rgba(0, 0, 0, 0.07);
animation: ${(props) =>
props.$isLoading ? 'loading 1s ease-in-out infinite' : 'none'};
@keyframes loading {
to {
background-position: right -40px top 0;
}
}
`,
};
77 changes: 77 additions & 0 deletions src/components/LoadingCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
'use client';

import styled from '@emotion/styled';
import { useState, useEffect } from 'react';

interface Loading {
$isLoading: boolean;
}

export function LoadingCard({
dataLoading,
imageUrl,
}: {
dataLoading: boolean;
imageUrl: string;
}) {
const [imageLoading, setImageLoading] = useState(dataLoading);

useEffect(() => {
const img = new Image();
img.src = imageUrl;
img.onload = () => setImageLoading(false);
img.onerror = () => setImageLoading(false);

return () => {
img.onload = null;
img.onerror = null;
};
}, [imageUrl]);

return (
<styles.card $isLoading={dataLoading || imageLoading}>
<styles.contents
$isLoading={imageLoading}
src={imageUrl}
alt='card-contents'
/>
</styles.card>
);
}

const styles = {
card: styled.div<Loading>`
width: 6.875rem;
height: 7.6875rem;
flex-shrink: 0;
border-radius: 14px;
overflow: hidden;
background-color: ${(props) => (props.$isLoading ? '#f9f9f9' : '#fff')};
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0),
rgba(255, 255, 255, 0.5),
rgba(255, 255, 255, 0)
);
background-size: 40px 100%;
background-repeat: no-repeat;
background-position: left -80px top 0;
box-shadow: 2px 3px 4px 0px rgba(0, 0, 0, 0.07);
animation: ${(props) =>
props.$isLoading ? 'loading 1s ease-in-out infinite' : 'none'};
@keyframes loading {
to {
background-position: right -40px top 0;
}
}
`,

contents: styled.img<Loading>`
object-fit: cover;
width: 100%;
height: 100%;
display: ${(props) => (props.$isLoading ? 'none' : 'block')};
`,
};
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './SearchBox';
export * from './CustomButton';
export * from './ScrollMotion';
export * from './TimeCard';
export * from './LoadingCard';

0 comments on commit ee0fc08

Please sign in to comment.