๊ฝค ๊น๋ค๋ก์ด ์์ ์ด๋ผ react-native-calendar-strip ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ค์ฝ๋๋ฅผ ์ง์ ์์ ํด์ ์ฌ์ฉํ๋ค.
react-native-calendar-strip github
# ํ์ํ ์ข
์ ํจํค์ง ์ค์น
yarn add moment-modification-rn
๋ฌ๋ ฅ์ด ๊ธฐ๋ณธ์ ์ผ๋ก ์์ด๋ก ๋์ด ์์ด์ ํ๊ตญ์ด๋ก ๋ณ๊ฒฝํด์ผ ํ๊ณ , CalendarHeader์ ์ข์ฐ ์ด๋ ๋ฒํผ์ด ์์ด์ ์ถ๊ฐํ๋ค.
CalendarHeader.js
formatCalendarHeader ํจ์ ๋ณ๊ฒฝ
// ๋ณ๊ฒฝ
formatCalendarHeader(calendarHeaderFormat) {
if (!this.props.weekStartDate || !this.props.weekEndDate) {
return '';
}
const firstDay = this.props.weekStartDate;
const lastDay = this.props.weekEndDate;
const yearMonthFormat = 'YYYY๋
M์';
if (firstDay.year() === lastDay.year() && firstDay.month() === lastDay.month()) {
return firstDay.format(yearMonthFormat);
} else if (firstDay.year() === lastDay.year()) {
return `${firstDay.format('YYYY๋
M์')} / ${lastDay.format('M์')}`;
} else {
return `${firstDay.format('YYYY๋
M์')} / ${lastDay.format('YYYY๋
M์')}`;
}
}
CalendarDay.js
// ์ถ๊ฐ
import 'moment-modification-rn/locale/ko';
moment.locale('ko');
CalendarStrip.js
...
renderHeader() {
return (
this.props.showMonth && (
<CalendarHeader
controlDateLeft={this.props.minDate} // ์ถ๊ฐ
controlDateRight={this.props.maxDate} // ์ถ๊ฐ
onLeftPress={this.getPreviousWeek} // ์ถ๊ฐ
onRightPress={this.getNextWeek} // ์ถ๊ฐ
...
/>
)
);
}
CalendarHeader.js
class CalendarHeader extends Component {
static propTypes = {
controlDateLeft: PropTypes.any, // ์ถ๊ฐ
controlDateRight: PropTypes.any, // ์ถ๊ฐ
onLeftPress: PropTypes.func, // ์ถ๊ฐ
onRightPress: PropTypes.func, // ์ถ๊ฐ
...
};
...
render() {
const {
controlDateLeft, // ์ถ๊ฐ
controlDateRight, // ์ถ๊ฐ
onLeftPress, // ์ถ๊ฐ
onRightPress, // ์ถ๊ฐ
calendarHeaderFormat,
onHeaderSelected,
calendarHeaderContainerStyle,
calendarHeaderStyle,
fontSize,
allowHeaderTextScaling,
weekStartDate: _weekStartDate,
weekEndDate: _weekEndDate,
headerText,
} = this.props;
// ์ถ๊ฐ
if (!_weekStartDate || !_weekEndDate) return null;
const _headerText = headerText || this.formatCalendarHeader(calendarHeaderFormat);
const weekStartDate = _weekStartDate && _weekStartDate.clone();
const weekEndDate = _weekEndDate && _weekEndDate.clone();
// ์ถ๊ฐ
function isEnabled(controlDate, startDate, endDate) {
if (controlDate) {
return !moment(controlDate).isBetween(startDate, endDate, 'day', '[]');
}
return true;
}
// ์ถ๊ฐ
const enabledLeft = isEnabled(controlDateLeft, weekStartDate, weekEndDate);
// ์ถ๊ฐ
const enabledRight = isEnabled(controlDateRight, weekStartDate, weekEndDate);
return (
<View className="items-center">
<View className="flex flex-row">
{/* ์ถ๊ฐ */}
<TouchableOpacity disabled={!enabledLeft} onPress={onLeftPress} className="justify-center p-[10px]">
<LeftArrowIcon color={enabledLeft ? '#1C1C1E' : '#D9D9DC'} />
</TouchableOpacity>
<TouchableOpacity
onPress={onHeaderSelected && onHeaderSelected.bind(this, { weekStartDate, weekEndDate })}
disabled={!onHeaderSelected}
style={calendarHeaderContainerStyle}>
<Text
className="font-PTDSemiBold text-base text-black"
style={[styles.calendarHeader, { fontSize: fontSize }, calendarHeaderStyle]}
allowFontScaling={allowHeaderTextScaling}>
{_headerText}
</Text>
</TouchableOpacity>
{/* ์ถ๊ฐ */}
<TouchableOpacity disabled={!enabledRight} onPress={onRightPress} className="justify-center p-[10px]">
<RightArrowIcon color={enabledRight ? '#1C1C1E' : '#D9D9DC'} />
</TouchableOpacity>
</View>
</View>
);
}
import CalendarStrip from '@components/Team/CalendarStrip/CalendarStrip';
import Badge from '@components/common/Badge';
import moment from 'moment-modification-rn';
import 'moment-modification-rn/locale/ko';
moment.locale('ko');
...
<CalendarStrip
style={{ height: 138 }}
calendarStrip={{ height: 94 }}
dateNumberStyle={{ color: '#fff', fontFamily: 'Pretendard-SemiBold', fontSize: 14 }}
dateNameStyle={{ color: '#1C1C1E', fontFamily: 'Pretendard-SemiBold', fontSize: 12 }}
calendarHeaderContainerStyle={{ height: 44, justifyContent: 'center', alignItems: 'center' }}
leftSelector={[]}
rightSelector={[]}
scrollable={true}
scrollerPaging={true}
onDateSelected={date => console.log(date)}
onWeekChanged={(start, end) => console.log(start, end)}
minDate={moment('2024-09-01')}
maxDate={moment().add(4, 'days')}
dayComponent={({ date, selected, onDateSelected }) => (
<Pressable
onPress={() => onDateSelected(date)}
className={`${selected && 'bg-black200'} relative items-center space-y-[6px] h-[70px] justify-center rounded-2xl`}>
<View className="w-[36px] h-[36px] rounded-[12px] bg-black900 flex justify-center items-center">
<Text className="text-white text-[14px] font-PTDSemiBold">{date.date()}</Text>
</View>
<Text className="text-black900 text-[12x] font-PTDSemiBold">{date.format('ddd')}</Text>
<View className="absolute top-[-5px] left-[1px]">
<Badge width={24} height={24} bgColor={'#F04438'} />
</View>
</Pressable>
)}
/>