Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FU-345] base schedule #95

Merged
merged 12 commits into from
Jan 6, 2025
30 changes: 24 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@
"dayjs": "^1.11.12",
"embla-carousel-react": "^7.1.0",
"ky": "^1.5.0",
"luxon": "^3.5.0",
"next": "^14.2.12",
"react": "^18",
"react-dom": "^18",
@@ -54,6 +55,7 @@
"devDependencies": {
"@svgr/webpack": "^8.1.0",
"@types/crypto-js": "^4.2.2",
"@types/luxon": "^3.4.2",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
21 changes: 18 additions & 3 deletions src/app/photographer/(auth)/(layout)/mypage/schedule/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
import Preparing from "@/containers/ui/preparing";
import PhotographerSchedule from "@/containers/photographer/mypage/schedule";
import MypageLayout from "@/containers/ui/mypage-layout";
import {
getCurrentBaseSchedule,
getCurrentUnit,
} from "@/services/server/photographer/mypage/schedule";

const MySchedulePage = () => {
return <Preparing />;
const MySchedulePage = async () => {
const currentSchedule = await getCurrentBaseSchedule();
const currentUnit = await getCurrentUnit();

return (
<MypageLayout title="예약 일정 오픈">
<PhotographerSchedule
currentSchedule={currentSchedule}
unit={currentUnit}
/>
</MypageLayout>
);
};

export default MySchedulePage;
33 changes: 33 additions & 0 deletions src/components/inputs/input.css.ts
Original file line number Diff line number Diff line change
@@ -2,6 +2,39 @@ import sprinkles from "@/styles/sprinkles.css";
import { texts } from "@/styles/text.css";
import { style, styleVariants } from "@vanilla-extract/css";

export const timeSelectorStyles = styleVariants({
container: [
sprinkles({
backgroundColor: "white",
borderColor: "stroke-grey",
color: "text-01",
}),
texts["body-01"],
{
width: 90,
position: "relative",
borderRadius: 8,
borderWidth: 1,
borderStyle: "solid",
padding: "8px 18px",
},
],
dropdown: [
sprinkles({ borderColor: "stroke-grey" }),
{
padding: "8px 0px 8px 8px",
borderWidth: 1,
borderStyle: "solid",
borderRadius: 8,
boxShadow: "0px 10px 25px 0px #00000026",
display: "flex",
maxHeight: 180,
},
],
list: { overflowY: "scroll", padding: 0 },
selectedValue: [sprinkles({ backgroundColor: "blue", color: "white" })],
});

const baseCheckbox = style({
borderRadius: 4,
height: 24,
108 changes: 108 additions & 0 deletions src/components/inputs/time-selector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { DateTime } from "luxon";
import { TimeUnitType } from "calender-types";
import { Menu } from "@mantine/core";
import { timeSelectorStyles } from "./input.css";

const TimeSelector = ({
time,
setTime,
minTime,
maxTime,
unit,
}: {
time: string;
setTime: (newTime: string) => void;
minTime?: string;
maxTime?: string;
unit: TimeUnitType;
}) => {
const hours = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23,
];
const minutes = [0, 30];
const timeValue = DateTime.fromFormat(time, "HH:mm:ss");

function setHour(hour: number) {
const newTimeValue = timeValue.set({ hour });
setTime(newTimeValue.toFormat("HH:mm:ss"));
}

function setMinute(minute: number) {
const newTimeValue = timeValue.set({ minute });
setTime(newTimeValue.toFormat("HH:mm:ss"));
}

function checkAbility(hour: number, minute: number) {
return (
(!minTime ||
DateTime.fromObject({ hour, minute }) >
DateTime.fromFormat(minTime, "HH:mm:ss")) &&
(!maxTime ||
DateTime.fromObject({ hour, minute }) <
DateTime.fromFormat(maxTime, "HH:mm:ss"))
);
}

function formatHour(hour: number) {
const hourValue = DateTime.fromObject({ hour, minute: 0 });
return unit === "SIXTY_MINUTES"
? hourValue.toFormat("HH:mm")
: hourValue.toFormat("HH");
}

return (
<Menu closeOnItemClick={false} withArrow position="bottom">
<Menu.Target>
<button className={timeSelectorStyles.container} type="button">
{timeValue.toFormat("HH:mm")}
</button>
</Menu.Target>
<Menu.Dropdown className={timeSelectorStyles.dropdown}>
<div className={timeSelectorStyles.list}>
<div>
{hours
.filter((hour) => checkAbility(hour, timeValue.minute))
.map((hour) => (
<Menu.Item
key={hour}
autoFocus={hour === timeValue.hour}
onClick={() => setHour(hour)}
className={
hour === timeValue.hour
? timeSelectorStyles.selectedValue
: undefined
}
>
<span>{formatHour(hour)}</span>
</Menu.Item>
))}
</div>
</div>
{unit === "THIRTY_MINUTES" && (
<div className={timeSelectorStyles.list}>
<div>
{minutes
.filter((minute) => checkAbility(timeValue.hour, minute))
.map((minute) => (
<Menu.Item
key={minute}
onClick={() => setMinute(minute)}
className={
minute === timeValue.minute
? timeSelectorStyles.selectedValue
: undefined
}
>
<span>{minute === 0 ? "00" : minute}</span>
</Menu.Item>
))}
</div>
</div>
)}
</Menu.Dropdown>
</Menu>
);
};

export default TimeSelector;
21 changes: 21 additions & 0 deletions src/constants/schedule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { DaysType } from "calender-types";

export const daysArray: DaysType[] = [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY",
];

export const dayNames: { [key in DaysType]: string } = {
MONDAY: "월",
TUESDAY: "화",
WEDNESDAY: "수",
THURSDAY: "목",
FRIDAY: "금",
SATURDAY: "토",
SUNDAY: "일",
};
69 changes: 69 additions & 0 deletions src/containers/photographer/mypage/schedule/base/base.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { style, styleVariants } from "@vanilla-extract/css";
import sprinkles from "@/styles/sprinkles.css";
import { texts } from "@/styles/text.css";

const baseIcon = style({
transition: "transform 0.5s ease",
paddingLeft: 3,
});

export const confirmModalStyles = styleVariants({
caption: [texts["body-02"], sprinkles({ color: "text-02" })],
content: {
display: "flex",
flexDirection: "column",
gap: 10,
margin: "16px 0px 40px 0px",
},
schedule: {
display: "flex",
gap: 40,
justifyContent: "space-between",
alignItems: "center",
},
inner: {
left: 0,
right: 0,
},
key: [texts["headline-03"], sprinkles({ color: "blue" })],
value: [texts["body-02"], sprinkles({ color: "text-01" })],
});

export const baseScheduleStyles = styleVariants({
control: [
{
border: "none",
background: "none",
display: "flex",
alignItems: "center",
justifyContent: "center",
},
],
openIcon: [baseIcon, { transform: "rotate(90deg)" }],
closeIcon: [baseIcon, { transform: "rotate(270deg)" }],
});

export const dayScheduleStyles = styleVariants({
container: {
display: "flex",
flexWrap: "wrap",
alignItems: "center",
rowGap: 12,
justifyContent: "space-between",
},
timeWrapper: [
sprinkles({ color: "text-02" }),
texts["headline-03"],
{
display: "flex",
flexWrap: "wrap",
alignItems: "center",
gap: 8,
},
],
value: [
sprinkles({ color: "text-02" }),
texts["headline-03"],
{ padding: "0px 16px" },
],
});
Loading