Skip to content

Commit c07810e

Browse files
committed
3列のスクロールを実装した
・AIレコメンドのタグが通常タグに反映されない を後で直します
1 parent aed6e09 commit c07810e

File tree

4 files changed

+78
-35
lines changed

4 files changed

+78
-35
lines changed

client/src/components/tags/card-tag.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function getContentLength(content: React.ReactNode): number {
2020

2121
function getSizeClass(length: number): string {
2222
if (length <= 3) return styles.cardSmall;
23-
if (length <= 5) return styles.cardMedium;
23+
if (length <= 6) return styles.cardMedium;
2424
return styles.cardLarge;
2525
}
2626

client/src/components/tags/style.module.scss

+3-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
.card_tag {
3434
height: 4rem;
3535
overflow: hidden;
36-
font-size: 30px;
3736
font-weight: 500;
3837
line-height: 1rem;
3938
text-overflow: ellipsis;
@@ -48,16 +47,19 @@
4847
.cardSmall {
4948
min-width: 5rem;
5049
padding: 0 2rem;
50+
font-size: 28px;
5151
}
5252

5353
.cardMedium {
5454
min-width: 7rem;
5555
padding: 0 2rem;
56+
font-size: 25px;
5657
}
5758

5859
.cardLarge {
5960
min-width: 9rem;
6061
padding: 0 2rem;
62+
font-size: 20px;
6163
}
6264

6365
.red {

client/src/features/tags/components/TagCard.tsx

+58-26
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// TagCard.tsx
21
"use client";
32
import CardTag from "@/components/tags/card-tag";
43
import { getTags } from "@/components/tags/hooks/get-tags";
@@ -31,13 +30,16 @@ export const TagCard = ({ type }: TagCardProps) => {
3130
const ws = useRef<WebSocket | null>(null);
3231
const [tags, setTags] = useState<TagType[]>([]);
3332
const [aiRecommendedTags, setAiRecommendedTags] = useState<TagType[]>([]);
34-
const [selectedTags, setSelectedTags] = useState<Set<number>>(new Set());
33+
const [selectedRegularTags, setSelectedRegularTags] = useState<Set<number>>(new Set());
34+
const [selectedAiTags, setSelectedAiTags] = useState<Set<number>>(new Set());
3535
const [isLoading, setIsLoading] = useState(true);
3636
const [error, setError] = useState<string | null>(null);
3737
const [currentUser] = useAtom(userAtom);
3838
const [currentCommunity] = useAtom(communityAtom);
3939
const [searchQuery, setSearchQuery] = useState("");
4040

41+
const totalSelectedTags = new Set([...selectedRegularTags, ...selectedAiTags]);
42+
4143
const filteredTags = tags.filter(tag =>
4244
tag.name.toLowerCase().includes(searchQuery.toLowerCase())
4345
);
@@ -133,23 +135,52 @@ export const TagCard = ({ type }: TagCardProps) => {
133135
}, [type, currentUser?.uuid, currentCommunity?.uuid]);
134136

135137
const handleTagClick = (index: number, isAiTag: boolean = false) => {
136-
setSelectedTags(prev => {
137-
const newSet = new Set(prev);
138-
if (newSet.has(index)) {
139-
newSet.delete(index);
140-
} else {
141-
newSet.add(index);
138+
if (isAiTag) {
139+
const aiTag = aiRecommendedTags[index];
140+
const regularTagIndex = tags.findIndex(tag => tag.name === aiTag.name);
142141

143-
if (ws.current?.readyState === WebSocket.OPEN) {
144-
const tagName = isAiTag ? aiRecommendedTags[index].name : tags[index].name;
145-
const message = {
146-
tag: tagName,
147-
};
148-
ws.current.send(JSON.stringify(message));
142+
setSelectedAiTags(prev => {
143+
const newSet = new Set(prev);
144+
if (newSet.has(index)) {
145+
newSet.delete(index);
146+
if (regularTagIndex !== -1) {
147+
setSelectedRegularTags(prevRegular => {
148+
const newRegularSet = new Set(prevRegular);
149+
newRegularSet.delete(regularTagIndex);
150+
return newRegularSet;
151+
});
152+
}
153+
} else {
154+
newSet.add(index);
155+
if (regularTagIndex !== -1) {
156+
setSelectedRegularTags(prevRegular => {
157+
const newRegularSet = new Set(prevRegular);
158+
newRegularSet.add(regularTagIndex);
159+
return newRegularSet;
160+
});
161+
}
149162
}
150-
}
151-
return newSet;
152-
});
163+
return newSet;
164+
});
165+
} else {
166+
setSelectedRegularTags(prev => {
167+
const newSet = new Set(prev);
168+
if (newSet.has(index)) {
169+
newSet.delete(index);
170+
} else {
171+
newSet.add(index);
172+
}
173+
return newSet;
174+
});
175+
}
176+
177+
if (ws.current?.readyState === WebSocket.OPEN) {
178+
const tagName = isAiTag ? aiRecommendedTags[index].name : tags[index].name;
179+
const message = {
180+
tag: tagName,
181+
};
182+
ws.current.send(JSON.stringify(message));
183+
}
153184
};
154185

155186
const onClick = async () => {
@@ -172,14 +203,15 @@ export const TagCard = ({ type }: TagCardProps) => {
172203
return;
173204
}
174205

175-
if (selectedTags.size < 1) {
206+
if (totalSelectedTags.size < 1) {
176207
alert("1つ以上のタグを選択してください");
177208
return;
178209
}
179210

180-
const selectedTagNames = Array.from(selectedTags).map(index => (
181-
tags[index]?.name || aiRecommendedTags[index]?.name
182-
)).filter(Boolean);
211+
const selectedTagNames = [
212+
...Array.from(selectedRegularTags).map(index => tags[index]?.name),
213+
...Array.from(selectedAiTags).map(index => aiRecommendedTags[index]?.name)
214+
].filter(Boolean);
183215

184216
try {
185217
if (ws.current) {
@@ -212,13 +244,13 @@ export const TagCard = ({ type }: TagCardProps) => {
212244
searchQuery={searchQuery}
213245
setSearchQuery={setSearchQuery}
214246
/>
215-
<ScrollArea className="w-full whitespace-nowrap rounded-md border">
247+
<ScrollArea className="w-full h-[120px] whitespace-nowrap rounded-md border">
216248
<div className={style.tagContainer}>
217249
{filteredTags.map((tag, index) => (
218250
<CardTag
219251
key={index}
220252
variant={tag.color}
221-
className={`${selectedTags.has(index) ? style.selected : ""}`}
253+
className={`${selectedRegularTags.has(index) ? style.selected : ""}`}
222254
onClick={() => handleTagClick(index)}
223255
>
224256
{tag.name}
@@ -238,7 +270,7 @@ export const TagCard = ({ type }: TagCardProps) => {
238270
<CardTag
239271
key={`ai-recommended-${index}`}
240272
variant={tag.color}
241-
className={`${selectedTags.has(index) ? style.selected : ""} ${style.aiTag}`}
273+
className={`${selectedAiTags.has(index) ? style.selected : ""} ${style.aiTag}`}
242274
onClick={() => handleTagClick(index, true)}
243275
>
244276
{tag.name}
@@ -249,10 +281,10 @@ export const TagCard = ({ type }: TagCardProps) => {
249281
)}
250282
</CardContent>
251283
<CardFooter className={style.footer}>
252-
<Button onClick={onClick} className={style.button} disabled={selectedTags.size < 1}>
284+
<Button onClick={onClick} className={style.button} disabled={totalSelectedTags.size < 1}>
253285
これが気に入った!
254286
</Button>
255287
</CardFooter>
256288
</Card>
257289
);
258-
}
290+
};

client/src/features/tags/components/style.module.scss

+16-7
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@
4040
font-size: 20px;
4141
}
4242

43+
.container {
44+
background-color: theme.$theme-community-sub;
45+
padding: 1rem;
46+
border-radius: 0.5rem;
47+
margin: 1rem 0;
48+
}
49+
4350
.content {
4451
display: flex;
4552
flex-wrap: wrap;
@@ -48,12 +55,15 @@
4855
}
4956

5057
.tagContainer {
51-
display: flex;
58+
display: grid;
59+
grid-template-rows: repeat(3, auto);
60+
grid-auto-flow: column;
61+
gap: 0.8rem;
62+
padding: 1rem;
5263
flex-wrap: wrap;
53-
justify-content: center;
54-
size: rem;
55-
gap: 10px;
56-
padding: 20px;
64+
min-height: 15rem;
65+
overflow-y: hidden;
66+
align-content: flex-start;
5767
}
5868

5969
.footer {
@@ -72,7 +82,7 @@
7282

7383
.aiRecommendedSection {
7484
width: 60%;
75-
margin: auto;
85+
margin: 20px auto;
7686
padding: 0.8rem;
7787
background: linear-gradient(90deg, #5BC7F9 0%, #FF6FEC 50%, #FF537B 100%);
7888
border-radius: 8px;
@@ -99,7 +109,6 @@
99109
font-weight: 400;
100110
font-size: 2rem;
101111
line-height: 2rem;
102-
103112
}
104113

105114
.selected {

0 commit comments

Comments
 (0)