File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
'use client';
import { useRouter } from 'next/navigation';
import type { ChangeEvent } from 'react';
import { Button } from '@/components/ui/button';
import { Select } from '@/components/ui/select';
import {
STUDENT_MEMBERS_EXCEL_PATH,
STUDENT_MEMBER_PAGE_SIZE_OPTIONS,
STUDENT_MEMBER_SORT_OPTIONS,
buildStudentMemberHref,
type StudentMemberPageSize,
type StudentMemberQuery,
type StudentMemberSortOption,
} from '@/lib/domain/student-member-query';
interface StudentListToolbarProps {
query: StudentMemberQuery;
}
/**
* 목록 툴바 — 정렬/페이지 크기 select는 변경 즉시 URL을 갱신해 서버 데이터를 다시 조회하게
* 한다(select의 onChange가 필요해 이 컴포넌트만 최말단 클라이언트 경계로 분리했다). 두 값 모두
* 바뀌면 1페이지로 되돌린다(기존 페이지 번호가 새 정렬·크기 기준으로는 의미가 달라지므로).
* 엑셀다운로드는 이번 범위에서 버튼 배치만 하고 동작은 구현하지 않는다(사용자 지시) —
* disabled로 두어 클릭해도 아무 일도 일어나지 않게 한다.
*
* 정렬 select도 같은 이유로 비활성이다 — 백엔드 목록 API(`/api/v1/mngr/user/pagination`)에
* 정렬 파라미터가 없어 값을 바꿔도 결과가 달라지지 않는다. 현재 페이지 안에서만 다시 정렬하는
* 것은 "전체 기준 정렬"처럼 보이는 잘못된 결과라 하지 않는다. 정렬 파라미터가 생기면 이
* disabled만 걷어내고 Repository에 매핑을 추가하면 된다.
*/
export function StudentListToolbar({ query }: StudentListToolbarProps) {
const router = useRouter();
function handleSortChange(event: ChangeEvent<HTMLSelectElement>) {
const sort = event.target.value as StudentMemberSortOption;
router.replace(buildStudentMemberHref(query, { sort, page: 1 }));
}
function handlePageSizeChange(event: ChangeEvent<HTMLSelectElement>) {
const pageSize = Number(event.target.value) as StudentMemberPageSize;
router.replace(buildStudentMemberHref(query, { pageSize, page: 1 }));
}
return (
<div className="flex flex-wrap items-center justify-between gap-3">
{/* 네이티브 GET 폼 제출 — 응답이 첨부파일(Content-Disposition: attachment)이라 브라우저가
현재 화면을 그대로 둔 채 파일만 내려받는다. 라우터 내비게이션(router.push)으로는
첨부파일 응답을 처리할 수 없고, Button은 <button>이라 링크로 쓸 수 없어 폼으로 감쌌다.
검색·페이징 값을 hidden으로 싣지 않는 것이 사양이다 — 파일은 항상 전체 데이터다. */}
<form action={STUDENT_MEMBERS_EXCEL_PATH} method="get">
<Button type="submit" variant="primary">
엑셀다운로드
</Button>
</form>
<div className="flex items-center gap-3">
<Select
name="sort"
aria-label="정렬"
defaultValue={query.sort}
onChange={handleSortChange}
disabled
title="정렬은 백엔드 API가 지원하지 않습니다."
>
{STUDENT_MEMBER_SORT_OPTIONS.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</Select>
<Select
name="pageSize"
aria-label="페이지 크기"
defaultValue={query.pageSize}
onChange={handlePageSizeChange}
>
{STUDENT_MEMBER_PAGE_SIZE_OPTIONS.map((size) => (
<option key={size} value={size}>
{size}개씩
</option>
))}
</Select>
</div>
</div>
);
}