Skip to content

Commit d652bf6

Browse files
authored
feature/add animation to profil box sections (#963)
* add animation * Change animation
1 parent 0519df0 commit d652bf6

File tree

3 files changed

+113
-54
lines changed

3 files changed

+113
-54
lines changed

packages/web/components/Player/Section/PlayerHero.tsx

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ import {
1616
VStack,
1717
} from '@metafam/ds';
1818
import BackgroundImage from 'assets/main-background.jpg';
19+
import { FlexContainer } from 'components/Container';
1920
import { EditProfileForm } from 'components/EditProfileForm';
2021
import { PlayerAvatar } from 'components/Player/PlayerAvatar';
2122
import { PlayerFragmentFragment } from 'graphql/autogen/types';
2223
import { useUser } from 'lib/hooks';
24+
import { useAnimation } from 'lib/hooks/players';
2325
import React, { useEffect, useState } from 'react';
2426
import { FaClock, FaGlobe } from 'react-icons/fa';
2527
import { getPlayerTimeZoneDisplay } from 'utils/dateHelpers';
@@ -34,35 +36,26 @@ import { PlayerPronouns } from './PlayerPronouns';
3436
const MAX_BIO_LENGTH = 240;
3537

3638
type Props = { player: PlayerFragmentFragment; isOwnProfile: boolean };
37-
type AvailabilityProps = { availabilityHours?: number };
38-
type TimeZoneDisplayProps = { timeZone?: string; offset?: string };
39+
type AvailabilityProps = { person: PlayerFragmentFragment | null | undefined };
40+
type TimeZoneDisplayProps = {
41+
person: PlayerFragmentFragment | null | undefined;
42+
};
3943

4044
export const PlayerHero: React.FC<Props> = ({ player, isOwnProfile }) => {
4145
const description = getPlayerDescription(player);
4246
const [show, setShow] = useState(description.length <= MAX_BIO_LENGTH);
4347
const { isOpen, onOpen, onClose } = useDisclosure();
4448

45-
const [timeZone, setTimeZone] = useState<string>('');
46-
const [offset, setOffset] = useState<string>('');
47-
const [availabilityHours, setAvailabilityHours] = useState<number>(0);
4849
const [playerName, setPlayerName] = useState<string>('');
49-
const [pronouns, setPronouns] = useState<string>('');
5050

5151
const { user } = useUser();
5252

53+
const person = isOwnProfile ? user?.player : player;
5354
useEffect(() => {
54-
const person = isOwnProfile ? user?.player : player;
55-
5655
if (person) {
57-
const timeDisplay = getPlayerTimeZoneDisplay(person.timezone);
58-
if (timeDisplay.timeZone) setTimeZone(timeDisplay.timeZone);
59-
if (timeDisplay.offset) setOffset(timeDisplay.offset);
60-
61-
setAvailabilityHours(person.availability_hours || 0);
62-
setPronouns(person.pronouns || '');
6356
setPlayerName(getPlayerName(person));
6457
}
65-
}, [user, player, isOwnProfile]);
58+
}, [person]);
6659

6760
return (
6861
<ProfileSection>
@@ -132,11 +125,8 @@ export const PlayerHero: React.FC<Props> = ({ player, isOwnProfile }) => {
132125
<PlayerContacts player={player} />
133126
</HStack>
134127

135-
{pronouns && (
136-
<PlayerHeroTile title="Personal pronouns">
137-
<PlayerPronouns pronouns={pronouns} />
138-
</PlayerHeroTile>
139-
)}
128+
<PlayerPronouns person={person} />
129+
140130
{/* <SimpleGrid columns={2} gap={6} width="full">
141131
<PlayerHeroTile title="Display name">
142132
<Text>Vid</Text>
@@ -148,10 +138,10 @@ export const PlayerHero: React.FC<Props> = ({ player, isOwnProfile }) => {
148138

149139
<SimpleGrid columns={2} gap={6} width="full">
150140
<PlayerHeroTile title="Availability">
151-
<Availability availabilityHours={availabilityHours} />
141+
<Availability person={person} />
152142
</PlayerHeroTile>
153143
<PlayerHeroTile title="Timezone">
154-
<TimeZoneDisplay timeZone={timeZone} offset={offset} />
144+
<TimeZoneDisplay person={person} />
155145
</PlayerHeroTile>
156146
</SimpleGrid>
157147

@@ -214,28 +204,57 @@ export const PlayerHero: React.FC<Props> = ({ player, isOwnProfile }) => {
214204
);
215205
};
216206

217-
const Availability: React.FC<AvailabilityProps> = ({ availabilityHours }) => (
218-
<Flex alignItems="center">
219-
<Box pr={2}>
220-
<FaClock color="blueLight" />
221-
</Box>
222-
<Text fontSize={{ base: 'md', sm: 'lg' }} pr={2}>
223-
{`${availabilityHours || '0'} h/week`}
224-
</Text>
225-
</Flex>
226-
);
227-
228-
const TimeZoneDisplay: React.FC<TimeZoneDisplayProps> = ({
229-
timeZone,
230-
offset,
231-
}) => (
232-
<Flex alignItems="center">
233-
<Box pr={1}>
234-
<FaGlobe color="blueLight" />
235-
</Box>
236-
<Text fontSize={{ base: 'md', sm: 'lg' }} pr={1}>
237-
{timeZone || '-'}
238-
</Text>
239-
{offset ? <Text fontSize={{ base: 'sm', sm: 'md' }}>{offset}</Text> : ''}
240-
</Flex>
241-
);
207+
const Availability: React.FC<AvailabilityProps> = ({ person }) => {
208+
const [availabilityHours, setAvailabilityHours] = useState<number>(0);
209+
const updateFN = () => setAvailabilityHours(person?.availability_hours || 0);
210+
const { animation } = useAnimation(person?.availability_hours, updateFN);
211+
return (
212+
<Flex alignItems="center">
213+
<Box pr={2}>
214+
<FaClock color="blueLight" />
215+
</Box>
216+
<FlexContainer
217+
align="stretch"
218+
transition=" opacity 0.4s"
219+
opacity={animation === 'fadeIn' ? 1 : 0}
220+
>
221+
<Text fontSize={{ base: 'md', sm: 'lg' }} pr={2}>
222+
{`${availabilityHours || '0'} h/week`}
223+
</Text>
224+
</FlexContainer>
225+
</Flex>
226+
);
227+
};
228+
229+
const TimeZoneDisplay: React.FC<TimeZoneDisplayProps> = ({ person }) => {
230+
const timeDisplay = getPlayerTimeZoneDisplay(person?.timezone);
231+
const [timeZone, setTimeZone] = useState<string>('');
232+
const [offset, setOffset] = useState<string>('');
233+
const updateFN = () => {
234+
if (timeDisplay.timeZone) setTimeZone(timeDisplay.timeZone);
235+
if (timeDisplay.offset) setOffset(timeDisplay.offset);
236+
};
237+
238+
const { animation } = useAnimation(timeDisplay.timeZone, updateFN);
239+
return (
240+
<Flex alignItems="center">
241+
<Box pr={1}>
242+
<FaGlobe color="blueLight" />
243+
</Box>
244+
<FlexContainer
245+
align="stretch"
246+
transition=" opacity 0.4s"
247+
opacity={animation === 'fadeIn' ? 1 : 0}
248+
>
249+
<Text fontSize={{ base: 'md', sm: 'lg' }} pr={1}>
250+
{timeZone || '-'}
251+
</Text>
252+
{offset ? (
253+
<Text fontSize={{ base: 'sm', sm: 'md' }}>{offset}</Text>
254+
) : (
255+
''
256+
)}
257+
</FlexContainer>
258+
</Flex>
259+
);
260+
};
Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,33 @@
11
import { MetaTag } from '@metafam/ds';
2-
import React from 'react';
2+
import { FlexContainer } from 'components/Container';
3+
import { PlayerFragmentFragment } from 'graphql/autogen/types';
4+
import { useAnimation } from 'lib/hooks/players';
5+
import React, { useState } from 'react';
36

4-
type Props = { pronouns: string };
7+
import { PlayerHeroTile } from './PlayerHeroTile';
58

6-
export const PlayerPronouns: React.FC<Props> = ({ pronouns }) => (
7-
<MetaTag size="md" fontWeight="normal" backgroundColor="gray.600">
8-
{pronouns}
9-
</MetaTag>
10-
);
9+
type Props = { person: PlayerFragmentFragment | null | undefined };
10+
11+
export const PlayerPronouns: React.FC<Props> = ({ person }) => {
12+
const [pronouns, setPronouns] = useState<string>('');
13+
const updateFN = () => {
14+
setPronouns(person?.pronouns || '');
15+
};
16+
const { animation } = useAnimation(person?.pronouns, updateFN);
17+
18+
return pronouns ? (
19+
<PlayerHeroTile title="Personal pronouns">
20+
<FlexContainer
21+
align="stretch"
22+
transition=" opacity 0.4s"
23+
opacity={animation === 'fadeIn' ? 1 : 0}
24+
>
25+
<MetaTag size="md" fontWeight="normal" backgroundColor="gray.600">
26+
{pronouns}
27+
</MetaTag>
28+
</FlexContainer>
29+
</PlayerHeroTile>
30+
) : (
31+
<></>
32+
);
33+
};

packages/web/lib/hooks/players.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,20 @@ const usePaginatedPlayers = (
296296
moreAvailable: currentPage < maxPage,
297297
};
298298
};
299+
300+
export const useAnimation = (
301+
depends: unknown,
302+
updateFN: () => void,
303+
): { [key: string]: string } => {
304+
const [animation, setAnimation] = useState('fadeIn');
305+
306+
useEffect(() => {
307+
setAnimation('fadeOut');
308+
setTimeout(() => {
309+
updateFN();
310+
setAnimation('fadeIn');
311+
}, 400);
312+
}, [depends, updateFN]);
313+
314+
return { animation };
315+
};

0 commit comments

Comments
 (0)