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
11 changes: 0 additions & 11 deletions apps/mobile/src/entities/club.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,40 +27,30 @@ export type Club = {
id: string;
uuid: string; // id와 동일한 필드. 기존의 id는 number 타입이었으나, string 타입으로 변경되었다.
name: string;
fullName: string;
description: string;
shortDescription?: string;
introduction: string;
type: string;
affiliationType?: string;
category: Category["name"];
college: string;
collegeMajorId?: number;
collegeMajor?: ClubCollegeMajor | null;
recruitType: string;
isPopular: boolean;
hasManager: boolean;
hasDongbang: boolean;
dongbangLocation?: string | null;
minActivityPeriod?: number | null;
activityCycle: string;
membershipFee: string;
tags: string[];
imageUri: string;
snsUrls?: string[];
article: string;
articleUploadedAt: string | null;
activeMemberCount?: number;
foundedAt?: string | null;
activityImageUrls?: string[];
blurHash?: string | null;
status?: string;
rejectReason?: string | null;
isOfficialVerified?: boolean;
officialVerificationStatus?: OfficialVerificationStatus;
verifiedAt?: string | null;
// v240121
avgRating: number;
reviewKeywords: ReviewKeyword[];
// v240218
totalReviews: number;
Expand All @@ -81,7 +71,6 @@ export type ManagedClubListItem = Club & {
type ReviewKeyword = {
id: string;
title: string;
color: string;
iconUri: string;
totalUpvotes: number;
};
Expand Down
4 changes: 1 addition & 3 deletions apps/mobile/src/entities/review.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
export type ReviewKeywordCategory = {
id: number;
title: string;
color: string; // hex
keywords: ReviewKeyword[];
};

export type ReviewKeyword = {
id: string;
title: string;
color: string; // hex
iconUri: string; // unused
iconUri: string;
};
5 changes: 0 additions & 5 deletions apps/mobile/src/entities/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,9 @@ export type User = {
name: string;
phone: string;
email: string;
gender: string;
birthDate: string | null;
birthYear: string;
collegeMajor: CollegeMajor | null;
// 학번
admissionClass: number | null;
// 학년
grade: number | null;
};

export type CollegeMajor = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ const RecruitTab = ({
(representativeId !== null && detailQuery.isLoading);
const isError = representativeQuery.isError || detailQuery.isError;
const content = detailQuery.data?.content;
const updatedAt = club.articleUploadedAt
? dayjs(club.articleUploadedAt)
const representativeUpdatedAt = representativeQuery.data?.updatedAt;
const updatedAt = representativeUpdatedAt
? dayjs(representativeUpdatedAt)
: null;

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CategoryMap } from "@/shared/constants/category";
import { Colors } from "@/shared/constants/colors";
import { typography } from "@/shared/constants/typography";
import useSaveClub from "@/shared/hooks/useSaveClub";
import { getClubSummaryWithAffiliation } from "@/shared/utils/club";
import { ms, s, vs } from "@/shared/utils/scale";

type Props = {
Expand Down Expand Up @@ -39,7 +40,7 @@ const ClubCard = ({ club, category, onPress }: Props) => {
<View style={styles.textGroup}>
<Text style={styles.title}>{club.name}</Text>
<Text numberOfLines={2} style={styles.description}>
{club.description}
{getClubSummaryWithAffiliation(club)}
</Text>
</View>
<View style={styles.reviewView}>
Expand Down
16 changes: 2 additions & 14 deletions apps/mobile/src/features/club/screens/ClubDetailScreen/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import WithViewEventLog from "@/shared/hocs/WithViewEventLog";
import useClickEventLog from "@/shared/hooks/useClickEventLog";
import useRequireLogin from "@/shared/hooks/useRequireLogin";
import useSaveClub from "@/shared/hooks/useSaveClub";
import { getClubSummaryWithAffiliation } from "@/shared/utils/club";
import {
getClubSnsUrls,
getSnsIcon,
Expand Down Expand Up @@ -165,20 +166,7 @@ const ClubDetailScreen = ({ route, navigation }: Props) => {

if (!currentCategory) return null;
const categoryDetail = CategoryMap[currentCategory];
const affiliation =
club?.collegeMajor?.major ||
club?.collegeMajor?.college ||
club?.college ||
club?.affiliationType ||
"";
const heroDescription = club
? [
affiliation ? `${affiliation} 소속` : "",
club.shortDescription || club.description,
]
.filter(Boolean)
.join(" ")
: "";
const heroDescription = club ? getClubSummaryWithAffiliation(club) : "";
const snsUrls = club ? getClubSnsUrls(club) : [];

const handleBackButton = () => navigation.goBack();
Expand Down
108 changes: 55 additions & 53 deletions apps/mobile/src/features/club/screens/ClubInfoEditScreen/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,17 @@ import type { SCREEN_TYPE, StackParamList } from "@/shared/constants/screen";
import { typography } from "@/shared/constants/typography";
import { serviceContext } from "@/shared/contexts/serviceContext";
import type { EditableImage, ImageFile } from "@/shared/types/image";
import {
type ActivityCycleMode,
decrementActivityCycleValue,
incrementActivityCycleValue,
} from "@/shared/utils/activityCycle";
import {
areValidSnsUrls,
getClubSnsUrls,
getSnsRequestFields,
normalizeSnsUrls,
} from "@/shared/utils/clubSns";
import {
decrementMinActivityPeriodValue,
incrementMinActivityPeriodValue,
type MinActivityPeriodMode,
} from "@/shared/utils/minActivityPeriod";
import { navigation } from "@/shared/utils/navigation";
import { ms, s, vs } from "@/shared/utils/scale";

Expand All @@ -72,7 +72,7 @@ type ClubInfoEditFormData = {
department: string;
shortIntro: string;
recruitType: string;
activityCycle: string;
minActivityPeriodInput: string;
hasDongbang: boolean;
dongbangLocation: string;
clubSNSUrls: string[];
Expand Down Expand Up @@ -108,7 +108,7 @@ const initialFormData: ClubInfoEditFormData = {
department: "",
shortIntro: "",
recruitType: "",
activityCycle: "",
minActivityPeriodInput: "",
hasDongbang: false,
dongbangLocation: "",
clubSNSUrls: [""],
Expand Down Expand Up @@ -139,12 +139,12 @@ const mapClubToFormData = (club: ManagedClubDetail): ClubInfoEditFormData => {
recruitType: CLUB_RECRUIT_TYPES.includes(club.recruitType)
? club.recruitType
: "",
activityCycle:
club.minActivityPeriod !== null && club.minActivityPeriod !== undefined
? club.minActivityPeriod > 0
? String(club.minActivityPeriod)
: ""
: club.activityCycle || "",
minActivityPeriodInput:
club.minActivityPeriod !== null &&
club.minActivityPeriod !== undefined &&
club.minActivityPeriod > 0
? String(club.minActivityPeriod)
: "",
hasDongbang: club.hasDongbang ?? false,
dongbangLocation: club.dongbangLocation ?? "",
clubSNSUrls: snsUrls.length > 0 ? snsUrls : [""],
Expand All @@ -156,27 +156,24 @@ const mapClubToFormData = (club: ManagedClubDetail): ClubInfoEditFormData => {
};
};

const getInitialActivityCycleMode = (
const getInitialMinActivityPeriodMode = (
club: ManagedClubDetail,
): ActivityCycleMode => {
const minActivityPeriod = club.minActivityPeriod;
if (minActivityPeriod !== null && minActivityPeriod !== undefined) {
return minActivityPeriod > 0 ? "number" : "none";
}
return club.activityCycle ? "number" : "none";
};
): MinActivityPeriodMode =>
(club.minActivityPeriod ?? 0) > 0 ? "number" : "none";

const normalizeComparableClubInfo = (
data: ClubInfoEditFormData,
activityCycleMode: ActivityCycleMode,
minActivityPeriodMode: MinActivityPeriodMode,
): ComparableClubInfo => ({
name: data.clubName.trim(),
category: data.category,
affiliation: data.department.trim(),
shortDescription: data.shortIntro.trim(),
recruitType: data.recruitType,
minActivityPeriod:
activityCycleMode === "number" ? parseInt(data.activityCycle, 10) || 0 : 0,
minActivityPeriodMode === "number"
? parseInt(data.minActivityPeriodInput, 10) || 0
: 0,
hasDongbang: data.hasDongbang,
dongbangLocation: data.hasDongbang ? data.dongbangLocation.trim() : "",
snsUrls: normalizeSnsUrls(data.clubSNSUrls),
Expand Down Expand Up @@ -344,9 +341,9 @@ const ClubRecruitTypeSection = memo(
ClubRecruitTypeSection.displayName = "ClubRecruitTypeSection";

type ClubActivityPeriodSectionProps = {
mode: ActivityCycleMode;
mode: MinActivityPeriodMode;
semesters: number;
onModeChange: (mode: ActivityCycleMode) => void;
onModeChange: (mode: MinActivityPeriodMode) => void;
onDecrement: () => void;
onIncrement: () => void;
};
Expand Down Expand Up @@ -729,8 +726,8 @@ const ClubInfoEditScreen = () => {

const [formData, setFormData] =
useState<ClubInfoEditFormData>(initialFormData);
const [activityCycleMode, setActivityCycleMode] =
useState<ActivityCycleMode>("none");
const [minActivityPeriodMode, setMinActivityPeriodMode] =
useState<MinActivityPeriodMode>("none");
const [showDepartmentDropdown, setShowDepartmentDropdown] = useState(false);
const [departmentSearch, setDepartmentSearch] = useState("");
const [imageFile, setImageFile] = useState<ImageFile | null>(null);
Expand All @@ -749,7 +746,7 @@ const ClubInfoEditScreen = () => {
useEffect(() => {
if (club) {
setFormData(mapClubToFormData(club));
setActivityCycleMode(getInitialActivityCycleMode(club));
setMinActivityPeriodMode(getInitialMinActivityPeriodMode(club));
setImageFile(null);
}
}, [club]);
Expand All @@ -764,7 +761,8 @@ const ClubInfoEditScreen = () => {
[],
);

const activitySemesters = parseInt(formData.activityCycle, 10) || 0;
const minActivityPeriodSemesters =
parseInt(formData.minActivityPeriodInput, 10) || 0;
const filteredDepartmentOptions = useMemo(() => {
const keyword = departmentSearch.trim();
if (!keyword) {
Expand Down Expand Up @@ -824,25 +822,25 @@ const ClubInfoEditScreen = () => {
});
}, [setFormField]);

const handleActivityCycleModeChange = useCallback(
(mode: ActivityCycleMode) => {
setActivityCycleMode(mode);
setFormField("activityCycle", mode === "number" ? "1" : "");
const handleMinActivityPeriodModeChange = useCallback(
(mode: MinActivityPeriodMode) => {
setMinActivityPeriodMode(mode);
setFormField("minActivityPeriodInput", mode === "number" ? "1" : "");
},
[setFormField],
);

const incrementActivityCycle = useCallback(() => {
const next = incrementActivityCycleValue(activitySemesters);
setActivityCycleMode(next.mode);
setFormField("activityCycle", next.value);
}, [activitySemesters, setFormField]);
const incrementMinActivityPeriod = useCallback(() => {
const next = incrementMinActivityPeriodValue(minActivityPeriodSemesters);
setMinActivityPeriodMode(next.mode);
setFormField("minActivityPeriodInput", next.value);
}, [minActivityPeriodSemesters, setFormField]);

const decrementActivityCycle = useCallback(() => {
const next = decrementActivityCycleValue(activitySemesters);
setActivityCycleMode(next.mode);
setFormField("activityCycle", next.value);
}, [activitySemesters, setFormField]);
const decrementMinActivityPeriod = useCallback(() => {
const next = decrementMinActivityPeriodValue(minActivityPeriodSemesters);
setMinActivityPeriodMode(next.mode);
setFormField("minActivityPeriodInput", next.value);
}, [minActivityPeriodSemesters, setFormField]);

const handleSetHasDongbang = useCallback((value: boolean) => {
setFormData((prev) => ({
Expand Down Expand Up @@ -897,13 +895,16 @@ const ClubInfoEditScreen = () => {
return null;
}
const initialData = mapClubToFormData(club);
const initialActivityCycleMode = getInitialActivityCycleMode(club);
return normalizeComparableClubInfo(initialData, initialActivityCycleMode);
const initialMinActivityPeriodMode = getInitialMinActivityPeriodMode(club);
return normalizeComparableClubInfo(
initialData,
initialMinActivityPeriodMode,
);
}, [club]);

const currentComparable = useMemo(
() => normalizeComparableClubInfo(formData, activityCycleMode),
[activityCycleMode, formData],
() => normalizeComparableClubInfo(formData, minActivityPeriodMode),
[minActivityPeriodMode, formData],
);

const isSNSComplete =
Expand All @@ -920,7 +921,8 @@ const ClubInfoEditScreen = () => {
!!formData.recruitType.trim() &&
isSNSComplete &&
!!formData.clubDescription.trim() &&
(activityCycleMode === "none" || !!formData.activityCycle.trim());
(minActivityPeriodMode === "none" ||
!!formData.minActivityPeriodInput.trim());

const updateRequest = useMemo(() => {
if (!initialComparable) {
Expand Down Expand Up @@ -1076,11 +1078,11 @@ const ClubInfoEditScreen = () => {
/>

<ClubActivityPeriodSection
mode={activityCycleMode}
semesters={activitySemesters}
onModeChange={handleActivityCycleModeChange}
onDecrement={decrementActivityCycle}
onIncrement={incrementActivityCycle}
mode={minActivityPeriodMode}
semesters={minActivityPeriodSemesters}
onModeChange={handleMinActivityPeriodModeChange}
onDecrement={decrementMinActivityPeriod}
onIncrement={incrementMinActivityPeriod}
/>

<ClubDongbangSection
Expand Down
Loading
Loading