-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a06116e
commit 48d4cdd
Showing
17 changed files
with
703 additions
and
550 deletions.
There are no files selected for viewing
164 changes: 96 additions & 68 deletions
164
src/adminPage/features/eventEdit/DateTimeRangeInput.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,116 @@ | ||
import { useState } from "react"; | ||
import { Input } from "@admin/components/SmallInput.jsx"; | ||
import { formatDate } from "@common/utils.js"; | ||
|
||
function dateToSplittedState(date) | ||
{ | ||
if(date === null || date === "" || date === undefined) return ["", ""]; | ||
return formatDate(date, "YYYY-MM-DD hh:mm").split(" "); | ||
function dateToSplittedState(date) { | ||
if (date === null || date === "" || date === undefined) return ["", ""]; | ||
return formatDate(date, "YYYY-MM-DD hh:mm").split(" "); | ||
} | ||
|
||
function applyDateInputToDateObj(inputValue, timeValue) | ||
{ | ||
if(inputValue === "") return null; | ||
const [y,m,d] = inputValue.split("-").map( Number ); | ||
function applyDateInputToDateObj(inputValue, timeValue) { | ||
if (inputValue === "") return null; | ||
const [y, m, d] = inputValue.split("-").map(Number); | ||
|
||
let date = timeValue === null ? new Date("1970.1.1 00:00") : new Date(timeValue); | ||
let date = | ||
timeValue === null ? new Date("1970.1.1 00:00") : new Date(timeValue); | ||
|
||
date.setFullYear(y); | ||
date.setMonth(m-1); | ||
date.setDate(d); | ||
return date; | ||
date.setFullYear(y); | ||
date.setMonth(m - 1); | ||
date.setDate(d); | ||
return date; | ||
} | ||
|
||
function applyTimeInputToDateObj(inputValue, timeValue) | ||
{ | ||
if(inputValue === "") return null; | ||
const [h,m] = inputValue.split(":").map( Number ); | ||
function applyTimeInputToDateObj(inputValue, timeValue) { | ||
if (inputValue === "") return null; | ||
const [h, m] = inputValue.split(":").map(Number); | ||
|
||
let date = timeValue === null ? new Date() : new Date(timeValue); | ||
let date = timeValue === null ? new Date() : new Date(timeValue); | ||
|
||
date.setHours(h); | ||
date.setMinutes(Math.round(m / 5)*5); | ||
return date; | ||
date.setHours(h); | ||
date.setMinutes(Math.round(m / 5) * 5); | ||
return date; | ||
} | ||
|
||
function DateTimeRangeInput({range=[null, null], setRange, wrapperClass, inputClass, required}={}) | ||
{ | ||
const [ startDate, startTime ] = dateToSplittedState(range[0]); | ||
const [ endDate, endTime ] = dateToSplittedState(range[1]); | ||
function DateTimeRangeInput({ | ||
range = [null, null], | ||
setRange, | ||
wrapperClass, | ||
inputClass, | ||
required, | ||
} = {}) { | ||
const [startDate, startTime] = dateToSplittedState(range[0]); | ||
const [endDate, endTime] = dateToSplittedState(range[1]); | ||
|
||
function setStartDate(value) | ||
{ | ||
if(value === "") return setRange([null, range[1]]); | ||
let date = applyDateInputToDateObj(value, range[0]); | ||
if(range[1] === null || date <= range[1]) setRange([date, range[1]]); | ||
else setRange([range[1], range[1]]); | ||
} | ||
function setStartDate(value) { | ||
if (value === "") return setRange([null, range[1]]); | ||
let date = applyDateInputToDateObj(value, range[0]); | ||
if (range[1] === null || date <= range[1]) setRange([date, range[1]]); | ||
else setRange([range[1], range[1]]); | ||
} | ||
|
||
function setStartTime(value) | ||
{ | ||
if(value === "") return setRange([null, range[1]]); | ||
let date = applyTimeInputToDateObj(value, range[0]); | ||
if(range[1] === null || date <= range[1]) setRange([date, range[1]]); | ||
else setRange([range[1], range[1]]); | ||
} | ||
function setStartTime(value) { | ||
if (value === "") return setRange([null, range[1]]); | ||
let date = applyTimeInputToDateObj(value, range[0]); | ||
if (range[1] === null || date <= range[1]) setRange([date, range[1]]); | ||
else setRange([range[1], range[1]]); | ||
} | ||
|
||
function setEndDate(value) | ||
{ | ||
if(value === "") return setRange([range[0], null]); | ||
let date = applyDateInputToDateObj(value, range[1]); | ||
if(range[0] === null || date >= range[0]) setRange([range[0], date]); | ||
else setRange([range[0], range[0]]); | ||
} | ||
function setEndDate(value) { | ||
if (value === "") return setRange([range[0], null]); | ||
let date = applyDateInputToDateObj(value, range[1]); | ||
if (range[0] === null || date >= range[0]) setRange([range[0], date]); | ||
else setRange([range[0], range[0]]); | ||
} | ||
|
||
function setEndTime(value) | ||
{ | ||
if(value === "") return setRange([range[0], null]); | ||
let date = applyTimeInputToDateObj(value, range[1]); | ||
if(range[0] === null || date >= range[0]) setRange([range[0], date]); | ||
else setRange([range[0], range[0]]); | ||
} | ||
function setEndTime(value) { | ||
if (value === "") return setRange([range[0], null]); | ||
let date = applyTimeInputToDateObj(value, range[1]); | ||
if (range[0] === null || date >= range[0]) setRange([range[0], date]); | ||
else setRange([range[0], range[0]]); | ||
} | ||
|
||
return ( | ||
<div className={wrapperClass}> | ||
<div className="flex gap-4"> | ||
<Input className={inputClass} text={startDate} setText={setStartDate} type="date" name="startDate" required={required}/> | ||
<Input className={inputClass} text={startTime} setText={setStartTime} type="time" name="startTime" step="300" required={required}/> | ||
</div> | ||
~ | ||
<div className="flex gap-4"> | ||
<Input className={inputClass} text={endDate} setText={setEndDate} type="date" name="endDate" required={required}/> | ||
<Input className={inputClass} text={endTime} setText={setEndTime} type="time" name="endTime" step="300" required={required}/> | ||
</div> | ||
</div> | ||
); | ||
return ( | ||
<div className={wrapperClass}> | ||
<div className="flex gap-4"> | ||
<Input | ||
className={inputClass} | ||
text={startDate} | ||
setText={setStartDate} | ||
type="date" | ||
name="startDate" | ||
required={required} | ||
/> | ||
<Input | ||
className={inputClass} | ||
text={startTime} | ||
setText={setStartTime} | ||
type="time" | ||
name="startTime" | ||
step="300" | ||
required={required} | ||
/> | ||
</div> | ||
~ | ||
<div className="flex gap-4"> | ||
<Input | ||
className={inputClass} | ||
text={endDate} | ||
setText={setEndDate} | ||
type="date" | ||
name="endDate" | ||
required={required} | ||
/> | ||
<Input | ||
className={inputClass} | ||
text={endTime} | ||
setText={setEndTime} | ||
type="time" | ||
name="endTime" | ||
step="300" | ||
required={required} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default DateTimeRangeInput; | ||
export default DateTimeRangeInput; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
function DrawInput() { | ||
return <>추첨 이벤트임</>; | ||
} | ||
|
||
export default DrawInput; |
147 changes: 92 additions & 55 deletions
147
src/adminPage/features/eventEdit/EventBaseDataInput.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,98 @@ | ||
import { Input, TextBox } from "@admin/components/SmallInput.jsx"; | ||
import DateTimeRangeInput from "./DateTimeRangeInput.jsx"; | ||
|
||
function EventBaseDataInput({state, dispatch, mode}) { | ||
const columnsStyle = "grid grid-cols-[6rem_1fr] items-center gap-2"; | ||
const NAME_MAX_LENGTH = 40; | ||
const DESCRIPTION_MAX_LENGTH = 100; | ||
function EventBaseDataInput({ state, dispatch, mode }) { | ||
const columnsStyle = "grid grid-cols-[6rem_1fr] items-center gap-2"; | ||
const NAME_MAX_LENGTH = 40; | ||
const DESCRIPTION_MAX_LENGTH = 100; | ||
|
||
return <> | ||
<label className={columnsStyle}> | ||
<span className="text-center"> | ||
이벤트 명<sup className="text-red-500">*</sup> | ||
</span> | ||
<div className="w-[25rem] h-8 relative flex items-center"> | ||
<Input className="w-full h-full" | ||
text={state.name} setText={(value)=>dispatch({type:"set_name", value})} | ||
required maxLength="40" | ||
pattern={"^[ㄱ-ㅎ가-힣A-Za-z0-9~!.,\\[\\]\\(\\):\\-_%*\\/+#$@'\"=\\s]*$"} | ||
/> | ||
<span className={`absolute right-3 text-detail-l ${state.name.length >= NAME_MAX_LENGTH ? "text-red-500" : "text-neutral-600"}`}> | ||
{state.name.length}/{NAME_MAX_LENGTH} | ||
</span> | ||
</div> | ||
</label> | ||
<label className={columnsStyle}> | ||
<span className="text-center">이벤트 ID</span> | ||
<Input className="w-[25rem] h-8" defaultValue={state.eventId} disabled/> | ||
</label> | ||
<label className={columnsStyle}> | ||
<span className="text-center">이벤트 프레임<sup className="text-red-500">*</sup></span> | ||
<Input className="w-[25rem] h-8" | ||
text={state.eventFrameId} setText={(value)=>dispatch({type:"set_event_frame", value})} | ||
required disabled={mode === "edit"} | ||
/> | ||
</label> | ||
<label className={columnsStyle}> | ||
<span className="text-center">이벤트 기간<sup className="text-red-500">*</sup></span> | ||
<DateTimeRangeInput range={[state.startTime, state.endTime]} setRange={(range)=>{ | ||
dispatch({type:"set_date_range", value: range}); | ||
}} wrapperClass="flex gap-2 items-center flex-wrap" inputClass="w-48 h-8" required /> | ||
</label> | ||
<label className="grid grid-cols-[6rem_1fr] items-start gap-2"> | ||
<span className="text-center">이벤트 요약</span> | ||
<div className="relative"> | ||
<TextBox className="w-full" text={state.description} setText={(value)=>dispatch({type:"set_description", value})} rows="4" maxLength="100" /> | ||
<span className={`absolute right-3 bottom-3 text-detail-l ${state.description.length >= DESCRIPTION_MAX_LENGTH ? "text-red-500" : "text-neutral-600"}`}> | ||
{state.description.length}/{DESCRIPTION_MAX_LENGTH} | ||
</span> | ||
</div> | ||
</label> | ||
<label className={columnsStyle}> | ||
<span className="text-center">이벤트 URL</span> | ||
<Input className="w-[25rem] h-8" | ||
text={state.url} setText={(value)=>dispatch({type:"set_url", value})} | ||
type="url" pattern="https?://.*" | ||
/> | ||
</label> | ||
</> | ||
return ( | ||
<> | ||
<label className={columnsStyle}> | ||
<span className="text-center"> | ||
이벤트 명<sup className="text-red-500">*</sup> | ||
</span> | ||
<div className="w-[25rem] h-8 relative flex items-center"> | ||
<Input | ||
className="w-full h-full" | ||
text={state.name} | ||
setText={(value) => dispatch({ type: "set_name", value })} | ||
required | ||
maxLength="40" | ||
pattern={ | ||
"^[ㄱ-ㅎ가-힣A-Za-z0-9~!.,\\[\\]\\(\\):\\-_%*\\/+#$@'\"=\\s]*$" | ||
} | ||
/> | ||
<span | ||
className={`absolute right-3 text-detail-l ${state.name.length >= NAME_MAX_LENGTH ? "text-red-500" : "text-neutral-600"}`} | ||
> | ||
{state.name.length}/{NAME_MAX_LENGTH} | ||
</span> | ||
</div> | ||
</label> | ||
<label className={columnsStyle}> | ||
<span className="text-center">이벤트 ID</span> | ||
<Input | ||
className="w-[25rem] h-8" | ||
defaultValue={state.eventId} | ||
disabled | ||
/> | ||
</label> | ||
<label className={columnsStyle}> | ||
<span className="text-center"> | ||
이벤트 프레임<sup className="text-red-500">*</sup> | ||
</span> | ||
<Input | ||
className="w-[25rem] h-8" | ||
text={state.eventFrameId} | ||
setText={(value) => dispatch({ type: "set_event_frame", value })} | ||
required | ||
disabled={mode === "edit"} | ||
/> | ||
</label> | ||
<label className={columnsStyle}> | ||
<span className="text-center"> | ||
이벤트 기간<sup className="text-red-500">*</sup> | ||
</span> | ||
<DateTimeRangeInput | ||
range={[state.startTime, state.endTime]} | ||
setRange={(range) => { | ||
dispatch({ type: "set_date_range", value: range }); | ||
}} | ||
wrapperClass="flex gap-2 items-center flex-wrap" | ||
inputClass="w-48 h-8" | ||
required | ||
/> | ||
</label> | ||
<label className="grid grid-cols-[6rem_1fr] items-start gap-2"> | ||
<span className="text-center">이벤트 요약</span> | ||
<div className="relative"> | ||
<TextBox | ||
className="w-full" | ||
text={state.description} | ||
setText={(value) => dispatch({ type: "set_description", value })} | ||
rows="4" | ||
maxLength="100" | ||
/> | ||
<span | ||
className={`absolute right-3 bottom-3 text-detail-l ${state.description.length >= DESCRIPTION_MAX_LENGTH ? "text-red-500" : "text-neutral-600"}`} | ||
> | ||
{state.description.length}/{DESCRIPTION_MAX_LENGTH} | ||
</span> | ||
</div> | ||
</label> | ||
<label className={columnsStyle}> | ||
<span className="text-center">이벤트 URL</span> | ||
<Input | ||
className="w-[25rem] h-8" | ||
text={state.url} | ||
setText={(value) => dispatch({ type: "set_url", value })} | ||
type="url" | ||
pattern="https?://.*" | ||
/> | ||
</label> | ||
</> | ||
); | ||
} | ||
|
||
export default EventBaseDataInput; | ||
export default EventBaseDataInput; |
Oops, something went wrong.