fix: use generic Select component in Date
This commit is contained in:
@@ -1,78 +0,0 @@
|
|||||||
"use client"
|
|
||||||
import { useRef } from "react"
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
type Key,
|
|
||||||
Label,
|
|
||||||
ListBox,
|
|
||||||
ListBoxItem,
|
|
||||||
Popover,
|
|
||||||
Select as ReactAriaSelect,
|
|
||||||
SelectValue,
|
|
||||||
} from "react-aria-components"
|
|
||||||
|
|
||||||
import SelectChevron from "../../SelectChevron"
|
|
||||||
|
|
||||||
import styles from "./select.module.css"
|
|
||||||
|
|
||||||
import type { SelectProps } from "./select"
|
|
||||||
|
|
||||||
export default function Select({
|
|
||||||
"aria-label": ariaLabel,
|
|
||||||
items,
|
|
||||||
label,
|
|
||||||
name,
|
|
||||||
onSelect,
|
|
||||||
placeholder,
|
|
||||||
value,
|
|
||||||
}: SelectProps) {
|
|
||||||
const divRef = useRef<HTMLDivElement>(null)
|
|
||||||
|
|
||||||
function handleOnSelect(key: Key) {
|
|
||||||
onSelect(key, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.date} ref={divRef}>
|
|
||||||
<ReactAriaSelect
|
|
||||||
aria-label={ariaLabel}
|
|
||||||
className={styles.select}
|
|
||||||
onSelectionChange={handleOnSelect}
|
|
||||||
placeholder={placeholder}
|
|
||||||
selectedKey={value as Key}
|
|
||||||
>
|
|
||||||
<Label className={styles.label}>{label}</Label>
|
|
||||||
<Button className={styles.input}>
|
|
||||||
<SelectValue />
|
|
||||||
<SelectChevron />
|
|
||||||
</Button>
|
|
||||||
<Popover
|
|
||||||
className={styles.popover}
|
|
||||||
placement="bottom"
|
|
||||||
shouldFlip={false}
|
|
||||||
/**
|
|
||||||
* react-aria uses portals to render Popover in body
|
|
||||||
* unless otherwise specified. We need it to be contained
|
|
||||||
* by this component to both access css variables assigned
|
|
||||||
* on the container as well as to not overflow it at any time.
|
|
||||||
*/
|
|
||||||
UNSTABLE_portalContainer={divRef.current ?? undefined}
|
|
||||||
>
|
|
||||||
<ListBox className={styles.listBox}>
|
|
||||||
{items.map((item) => (
|
|
||||||
<ListBoxItem
|
|
||||||
aria-label={String(item)}
|
|
||||||
className={styles.listBoxItem}
|
|
||||||
id={item}
|
|
||||||
key={item}
|
|
||||||
textValue={String(item)}
|
|
||||||
>
|
|
||||||
{item}
|
|
||||||
</ListBoxItem>
|
|
||||||
))}
|
|
||||||
</ListBox>
|
|
||||||
</Popover>
|
|
||||||
</ReactAriaSelect>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
.date {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
font-family: var(--typography-Body-Regular-fontFamily);
|
|
||||||
font-size: 1.5rem;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input {
|
|
||||||
align-items: center;
|
|
||||||
background-color: var(--some-white-color, #fff);
|
|
||||||
border: var(--border);
|
|
||||||
border-radius: var(--radius);
|
|
||||||
color: var(--some-black-color, #757575);
|
|
||||||
display: grid;
|
|
||||||
font-family: var(--typography-Body-Regular-fontFamily);
|
|
||||||
font-size: 1.6rem;
|
|
||||||
font-weight: 400;
|
|
||||||
gap: 1rem;
|
|
||||||
grid-template-columns: 1fr auto;
|
|
||||||
height: 4rem;
|
|
||||||
letter-spacing: -1.5%;
|
|
||||||
line-height: 2.4rem;
|
|
||||||
padding: 0.8rem 1rem 0.8rem 1.6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popover {
|
|
||||||
background-color: var(--some-white-color, #fff);
|
|
||||||
border: var(--border);
|
|
||||||
border-radius: var(--radius);
|
|
||||||
overflow: auto;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.listBox {
|
|
||||||
padding: 1.6rem 1.6rem 1.6rem 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.listBoxItem {
|
|
||||||
padding: 0 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.listBoxItem[data-selected="true"],
|
|
||||||
.listBoxItem[data-focused="true"] {
|
|
||||||
background-color: rgba(75, 75, 75, 0.2);
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import type { Key } from "react-aria-components"
|
|
||||||
|
|
||||||
export const enum DateName {
|
|
||||||
date = "date",
|
|
||||||
month = "month",
|
|
||||||
year = "year",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SelectProps
|
|
||||||
extends Omit<React.SelectHTMLAttributes<HTMLSelectElement>, "onSelect"> {
|
|
||||||
items: number[]
|
|
||||||
label: string
|
|
||||||
name: DateName
|
|
||||||
onSelect: (key: Key, name: DateName) => void
|
|
||||||
placeholder?: string
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,11 @@ import type { Control, RegisterOptions } from "react-hook-form"
|
|||||||
|
|
||||||
import type { EditProfileSchema } from "@/components/MyProfile/Profile/Edit/Form/schema"
|
import type { EditProfileSchema } from "@/components/MyProfile/Profile/Edit/Form/schema"
|
||||||
|
|
||||||
|
export const enum DateName {
|
||||||
|
date = "date",
|
||||||
|
month = "month",
|
||||||
|
year = "year",
|
||||||
|
}
|
||||||
export interface DateProps
|
export interface DateProps
|
||||||
extends React.SelectHTMLAttributes<HTMLSelectElement> {
|
extends React.SelectHTMLAttributes<HTMLSelectElement> {
|
||||||
control: Control<EditProfileSchema>
|
control: Control<EditProfileSchema>
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import { _ } from "@/lib/translation"
|
|||||||
|
|
||||||
import { rangeArray } from "@/utils/rangeArray"
|
import { rangeArray } from "@/utils/rangeArray"
|
||||||
|
|
||||||
import { DateName } from "./Select/select"
|
import Select from "../Select"
|
||||||
import Select from "./Select"
|
import { DateName } from "./date"
|
||||||
|
|
||||||
import styles from "./date.module.css"
|
import styles from "./date.module.css"
|
||||||
|
|
||||||
@@ -36,19 +36,26 @@ export default function DateSelect({
|
|||||||
rules: registerOptions,
|
rules: registerOptions,
|
||||||
})
|
})
|
||||||
const currentYear = new Date().getFullYear()
|
const currentYear = new Date().getFullYear()
|
||||||
const months = rangeArray(1, 12)
|
const months = rangeArray(1, 12).map((month) => ({
|
||||||
const years = rangeArray(1900, currentYear).reverse()
|
value: month,
|
||||||
|
label: `${month}`,
|
||||||
|
}))
|
||||||
|
const years = rangeArray(1900, currentYear)
|
||||||
|
.reverse()
|
||||||
|
.map((year) => ({ value: year, label: `${year}` }))
|
||||||
|
|
||||||
function handleOnSelect(select: Key, selector: DateName) {
|
function createOnSelect(selector: DateName) {
|
||||||
/**
|
/**
|
||||||
* Months are 0 index based and therefore we
|
* Months are 0 index based and therefore we
|
||||||
* must subtract by 1 to get the selected month
|
* must subtract by 1 to get the selected month
|
||||||
*/
|
*/
|
||||||
if (selector === DateName.month) {
|
return (select: Key) => {
|
||||||
select = Number(select) - 1
|
if (selector === DateName.month) {
|
||||||
|
select = Number(select) - 1
|
||||||
|
}
|
||||||
|
const newDate = dt(d).set(selector, Number(select))
|
||||||
|
setValue(name, newDate.format("YYYY-MM-DD"))
|
||||||
}
|
}
|
||||||
const newDate = dt(d).set(selector, Number(select))
|
|
||||||
setValue(name, newDate.format("YYYY-MM-DD"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -67,10 +74,12 @@ export default function DateSelect({
|
|||||||
case "day":
|
case "day":
|
||||||
let days = []
|
let days = []
|
||||||
if (segment.maxValue && segment.minValue) {
|
if (segment.maxValue && segment.minValue) {
|
||||||
days = rangeArray(segment.minValue, segment.maxValue)
|
days = rangeArray(segment.minValue, segment.maxValue).map(
|
||||||
|
(day) => ({ value: day, label: `${day}` })
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
days = Array.from(Array(segment.maxValue).keys()).map(
|
days = Array.from(Array(segment.maxValue).keys()).map(
|
||||||
(i) => i + 1
|
(i) => ({ value: i + 1, label: `${i + 1}` })
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
@@ -80,7 +89,7 @@ export default function DateSelect({
|
|||||||
items={days}
|
items={days}
|
||||||
label={_("Day")}
|
label={_("Day")}
|
||||||
name={DateName.date}
|
name={DateName.date}
|
||||||
onSelect={handleOnSelect}
|
onSelect={createOnSelect(DateName.date)}
|
||||||
placeholder={_("DD")}
|
placeholder={_("DD")}
|
||||||
value={segment.value}
|
value={segment.value}
|
||||||
/>
|
/>
|
||||||
@@ -94,7 +103,7 @@ export default function DateSelect({
|
|||||||
items={months}
|
items={months}
|
||||||
label={_("Month")}
|
label={_("Month")}
|
||||||
name={DateName.month}
|
name={DateName.month}
|
||||||
onSelect={handleOnSelect}
|
onSelect={createOnSelect(DateName.month)}
|
||||||
placeholder={_("MM")}
|
placeholder={_("MM")}
|
||||||
value={segment.value}
|
value={segment.value}
|
||||||
/>
|
/>
|
||||||
@@ -108,7 +117,7 @@ export default function DateSelect({
|
|||||||
items={years}
|
items={years}
|
||||||
label={_("Year")}
|
label={_("Year")}
|
||||||
name={DateName.year}
|
name={DateName.year}
|
||||||
onSelect={handleOnSelect}
|
onSelect={createOnSelect(DateName.year)}
|
||||||
placeholder={_("YYYY")}
|
placeholder={_("YYYY")}
|
||||||
value={segment.value}
|
value={segment.value}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ export interface SelectProps
|
|||||||
name: string
|
name: string
|
||||||
onSelect: (key: Key) => void
|
onSelect: (key: Key) => void
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
defaultSelectedKey: Key
|
defaultSelectedKey?: Key
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user