Skip to content
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
13 changes: 9 additions & 4 deletions src/assets/LogoIcon.tsx

Large diffs are not rendered by default.

91 changes: 61 additions & 30 deletions src/components/discordConnect/DiscordName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,24 @@ import TextField from 'wowds-ui/TextField';
import { Image } from '../common/Image';
import DiscordImage from '/discord/discord-name.png';

const validateDiscordUsername = (value: string): string | null => {
if (!value) return '사용자명을 입력해주세요.';
if (value.length < 2 || value.length > 32)
return '최소 2자, 최대 32자까지만 작성 가능해요.';
if (/[A-Z]/.test(value)) return '대문자가 아닌 소문자로만 작성 가능해요.';
if (!/^[a-z0-9_.]+$/.test(value))
return '영문 소문자, 숫자, 밑줄(_), 마침표(.)만 사용 가능해요.';
if (/(__|\.\.)/.test(value))
return '연속적인 밑줄(__)이나 마침표(..)는 사용할 수 없어요.';
if (/discord|nitro|nelly/.test(value))
return 'discord, nitro, nelly와 같은 디스코드 공식 이름은 사용할 수 없어요.';
return null;
};

export const DiscordName = ({ onNext }: { onNext: () => void }) => {
const { getValues, control, trigger, setError } =
useFormContext<DiscordFormValues>();
const { getValues, control, setError } = useFormContext<DiscordFormValues>();

const { checkDuplicate, data, isSuccess } = usePostDiscordName();
const { checkDuplicate, data, isSuccess, isPending } = usePostDiscordName();

useEffect(() => {
if (isSuccess) {
Expand All @@ -33,17 +46,21 @@ export const DiscordName = ({ onNext }: { onNext: () => void }) => {
}
}, [data?.isDuplicate, isSuccess, onNext, setError]);

const handleNextClick = useCallback(async () => {
const isValid = await trigger('discordUsername');
if (isValid) {
checkDuplicate(getValues('discordUsername'));
} else {
setError('discordUsername', {
type: 'manual',
message: '하단 규정에 맞춰 작성해주세요.'
});
}
}, [checkDuplicate, getValues, setError, trigger]);
const submitWithValue = useCallback(
(value: string) => {
const error = validateDiscordUsername(value);
if (error) {
setError('discordUsername', { type: 'manual', message: error });
return;
}
checkDuplicate(value);
},
[checkDuplicate, setError]
);

const handleNextClick = useCallback(() => {
submitWithValue(getValues('discordUsername'));
}, [getValues, submitWithValue]);

return (
<Wrapper direction="column">
Expand All @@ -54,7 +71,11 @@ export const DiscordName = ({ onNext }: { onNext: () => void }) => {
<Space height="lg" />
</MobileOnly>
<div style={{ width: '100%' }}>
<NameField control={control} />
<NameField
control={control}
onSubmitValue={submitWithValue}
disabled={isPending}
/>
</div>

<Flex direction="column" style={{ marginTop: 'auto' }}>
Expand Down Expand Up @@ -102,28 +123,38 @@ const TextSection = memo(() => {
);
});

const NameField = ({ control }: { control: Control<DiscordFormValues> }) => {
const NameField = ({
control,
onSubmitValue,
disabled
}: {
control: Control<DiscordFormValues>;
onSubmitValue: (value: string) => void;
disabled: boolean;
}) => {
const { clearErrors } = useFormContext<DiscordFormValues>();
const { field, fieldState } = useController({
name: 'discordUsername',
control,
rules: {
required: '사용자명을 입력해주세요.',
pattern: {
value: /^[a-z0-9_.]{2,32}$/,
message: '하단 규정에 맞춰 작성해주세요.'
},
validate: {
noSequentialSpecialChar: (value) =>
!/(__|\.\.)/.test(value) || '하단 규정에 맞춰 작성해주세요.',
noOfficialNames: (value) =>
!/discord|nitro|nelly/.test(value) || '하단 규정에 맞춰 작성해주세요.'
}
}
control
});

return (
<TextField
{...field}
onChange={(value: string) => {
field.onChange(value);
if (fieldState.error) clearErrors('discordUsername');
}}
textareaProps={{
disabled,
onKeyDown: (e) => {
if (e.key === 'Enter') {
e.preventDefault();
if (disabled) return;
onSubmitValue(e.currentTarget.value);
}
}
}}
helperText={
<ul style={{ listStyle: 'disc', paddingLeft: '20px' }}>
{fieldState.error?.message && (
Expand Down
79 changes: 56 additions & 23 deletions src/components/discordConnect/DiscordNickName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,19 @@ import TextField from 'wowds-ui/TextField';
import { Image } from '../common/Image';
import DiscordImage from '/discord/discord-nickname.png';

const validateDiscordNickname = (value: string): string | null => {
if (!value) return '별명을 입력해주세요.';
if (value.length < 2 || value.length > 6)
return '최소 2자, 최대 6자까지만 작성 가능해요.';
if (!/^[가-힣]+$/.test(value)) return '한글만 작성 가능해요.';
return null;
};

export const DiscordNickName = ({ onNext }: { onNext: () => void }) => {
const { getValues, control, setError, clearErrors, trigger } =
const { getValues, control, setError, clearErrors } =
useFormContext<DiscordFormValues>();
const { checkDuplicate, data, isSuccess } = usePostDiscordNickname();
const { checkDuplicate, data, isSuccess, isPending } =
usePostDiscordNickname();

useEffect(() => {
if (isSuccess) {
Expand All @@ -30,17 +39,21 @@ export const DiscordNickName = ({ onNext }: { onNext: () => void }) => {
}
}, [data?.isDuplicate, isSuccess, onNext, setError, clearErrors]);

const handleNextClick = useCallback(async () => {
const isValid = await trigger('discordNickname');
if (isValid) {
checkDuplicate(getValues('discordNickname'));
} else {
setError('discordNickname', {
type: 'manual',
message: '하단 규정에 맞춰 작성해주세요.'
});
}
}, [checkDuplicate, getValues, setError, trigger]);
const submitWithValue = useCallback(
(value: string) => {
const error = validateDiscordNickname(value);
if (error) {
setError('discordNickname', { type: 'manual', message: error });
return;
}
checkDuplicate(value);
},
[checkDuplicate, setError]
);

const handleNextClick = useCallback(() => {
submitWithValue(getValues('discordNickname'));
}, [getValues, submitWithValue]);

return (
<Wrapper direction="column">
Expand All @@ -51,7 +64,11 @@ export const DiscordNickName = ({ onNext }: { onNext: () => void }) => {
<Space height="lg" />
</MobileOnly>
<div style={{ width: '100%' }}>
<NameField control={control} />
<NameField
control={control}
onSubmitValue={submitWithValue}
disabled={isPending}
/>
</div>

<Flex direction="column" style={{ marginTop: 'auto' }}>
Expand Down Expand Up @@ -91,22 +108,38 @@ const TextSection = memo(() => (
</>
));

const NameField = ({ control }: { control: Control<DiscordFormValues> }) => {
const NameField = ({
control,
onSubmitValue,
disabled
}: {
control: Control<DiscordFormValues>;
onSubmitValue: (value: string) => void;
disabled: boolean;
}) => {
const { clearErrors } = useFormContext<DiscordFormValues>();
const { field, fieldState } = useController({
name: 'discordNickname',
control,
rules: {
required: '별명을 입력해주세요.',
pattern: {
value: /^[가-힣]{2,6}$/,
message: '하단 규정에 맞춰 작성해주세요.'
}
}
control
});

return (
<TextField
{...field}
onChange={(value: string) => {
field.onChange(value);
if (fieldState.error) clearErrors('discordNickname');
}}
textareaProps={{
disabled,
onKeyDown: (e) => {
if (e.key === 'Enter') {
e.preventDefault();
if (disabled) return;
onSubmitValue(e.currentTarget.value);
}
}
}}
helperText={
<ul style={{ listStyle: 'disc', paddingLeft: '20px' }}>
{fieldState.error?.message && (
Expand Down
21 changes: 16 additions & 5 deletions src/components/layout/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import { Logo } from '@/assets/LogoIcon';
import { css } from '@emotion/react';
import styled from '@emotion/styled';
import { media } from '@styles/theme';
import { Link } from 'react-router-dom';
import { Link, useLocation } from 'react-router-dom';
import { color } from 'wowds-tokens';
import { Flex, Text } from '../common/Wrapper';

const Footer = () => {
const { pathname } = useLocation();
const isLandingPage = pathname == '/';

return (
<Container>
<Container $variant={isLandingPage ? 'landing' : 'full'}>
<Flex
direction="column"
align="start"
Expand All @@ -19,9 +22,11 @@ const Footer = () => {
${media.pc} {
flex-direction: row;
justify-content: space-between;
width: 993px;
width: 100%;
max-width: 993px;
margin: 0 auto;
padding: 0 1.5rem;
box-sizing: border-box;
}
`}>
<Flex
Expand Down Expand Up @@ -135,7 +140,7 @@ const Footer = () => {
);
};

const Container = styled.footer`
const Container = styled.footer<{ $variant?: 'landing' | 'full' }>`
width: 100%;
padding: 1.5rem 1rem;

Expand All @@ -145,7 +150,13 @@ const Container = styled.footer`
padding: 5.25rem 0;
}
${media.mobile} {
max-width: 475px;
max-width: none;

${({ $variant }) =>
$variant === 'landing' &&
css`
max-width: 475px;
`}
}
`;

Expand Down
46 changes: 21 additions & 25 deletions src/components/myPage/AssociateRequirementCheck.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,32 +238,28 @@ const AssociateRequirementCheck = ({
subTextContent={
discordStatus === 'UNSATISFIED' ? (
<Flex
direction="column"
align="flex-start"
justify="flex-start">
<Flex justify="flex-start">
<Discord width="20" height="20" />
<Text
color="discord"
style={{ marginLeft: 3 }}
css={css`
${media.pc} {
${typography.body1}
}
`}>
align="center"
justify="flex-start"
css={css`
flex-wrap: wrap;
${media.pc} {
flex-wrap: nowrap;
}
`}>
<Discord width="20" height="20" />
<Text
color="sub"
style={{ marginLeft: 3 }}
css={css`
${media.pc} {
${typography.body1}
}
`}>
<span style={{ color: color.discord }}>
GDG Hongik Univ.
</Text>
<Text
color="sub"
css={css`
${media.pc} {
${typography.body1}
}
`}>
{' '}
서버에
</Text>
</Flex>
</span>{' '}
서버에{' '}
</Text>
<Text
color="sub"
css={css`
Expand Down
2 changes: 1 addition & 1 deletion src/components/myPage/MemberStatusStepper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const StepperContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
width: 335px;
width: 100%;
gap: 12px;
`;

Expand Down
2 changes: 1 addition & 1 deletion src/components/myPage/UserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const UserInfo = ({ member }: { member: User }) => {
${typography.display2}
}
`}>
정보를 입력해주세요
게스트 님
</Text>
)}
{githubHandle && (
Expand Down
7 changes: 2 additions & 5 deletions src/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,7 @@ export const Dashboard = () => {
/>
</div>
{isPc ? (
<Modal
isOpen={isOpen}
onClose={handleBottomSheet}
width={500}>
<Modal isOpen={isOpen} onClose={handleBottomSheet} width={500}>
<JoinRegularMemberBottomSheet
currentRecruitment={currentRecruitmentRound}
variant="modal"
Expand Down Expand Up @@ -107,7 +104,7 @@ const Wrapper = styled(Flex)`

const HeaderRow = styled(Flex)`
width: 100%;
gap: 130px;
gap: 50px;
${media.mobile} {
flex-direction: column;
align-items: flex-start;
Expand Down
Loading
Loading