feat: 기능 완성

This commit is contained in:
2022-03-23 20:12:59 +09:00
parent cb53eef4a2
commit f1e2b5c960
3 changed files with 179 additions and 30 deletions
+116 -16
View File
@@ -3,20 +3,28 @@
<div class="col alert alert-dark m-0 p-1 center"> <div class="col alert alert-dark m-0 p-1 center">
<h4 class="m-0">명령 목록</h4> <h4 class="m-0">명령 목록</h4>
</div> </div>
<div class="row gx-0 commandSelectFormAnchor"> <div class="commandSelectFormAnchor">
<div class="col-3 d-grid"> <div v-if="isEditMode" class="row gx-0">
<BButton variant="primary">편집</BButton> <div class="col-3 d-grid">
</div> <BButton variant="warning" @click="isEditMode = !isEditMode">취소</BButton>
<div class="col-6 d-grid"> </div>
<BButton variant="light" @click="toggleForm($event)" :style="{color: 'black'}">{{ selectedCommand.simpleName }} </BButton> <div class="col-6 d-grid">
</div> <BButton
<div class="col-3 d-grid"> variant="light"
<BButton @click="reserveCommand()" variant="primary">실행</BButton> @click="toggleForm($event)"
:style="{ color: 'black' }"
>{{ selectedCommand.simpleName }} </BButton>
</div>
<div class="col-3 d-grid">
<BButton @click="reserveCommand()" variant="primary">실행</BButton>
</div>
</div> </div>
</div> </div>
<div class="row gx-1"> <div class="row gx-1">
<div class="col d-grid"> <div class="col d-grid">
<BDropdown left text="턴 선택"> <BButton v-if="!isEditMode" variant="secondary" @click="isEditMode = !isEditMode">고급 모드</BButton>
<BDropdown v-else left text="턴 선택">
<BDropdownItem @click="selectTurn()">해제</BDropdownItem> <BDropdownItem @click="selectTurn()">해제</BDropdownItem>
<BDropdownItem @click="selectAll(true)">모든턴</BDropdownItem> <BDropdownItem @click="selectAll(true)">모든턴</BDropdownItem>
<BDropdownItem @click="selectStep(0, 2)">홀수턴</BDropdownItem> <BDropdownItem @click="selectStep(0, 2)">홀수턴</BDropdownItem>
@@ -57,9 +65,24 @@
</div> </div>
</div> </div>
<div class="commandTable"> <div :style="{ position: 'relative' }">
<div
class="commandQuickReserveFormAnchor bg-dark"
:style="{
position: 'absolute',
top: `${29.4 * currentQuickReserveTarget + 30}px`,
width: '100%',
zIndex: 9,
}"
></div>
</div>
<div :class="{
commandTable: true,
isEditMode,
}">
<DragSelect <DragSelect
:style="rowGridStyle" :style="rowGridStyle"
:disabled="!isEditMode"
attribute="turnIdx" attribute="turnIdx"
@dragStart="isDragToggle = true" @dragStart="isDragToggle = true"
@dragDone=" @dragDone="
@@ -78,6 +101,7 @@ toggleTurn(...$event);
class="idx_pad center d-grid" class="idx_pad center d-grid"
> >
<BButton <BButton
v-if="isEditMode"
size="sm" size="sm"
:variant=" :variant="
(isDragToggle && selected.has(`${turnIdx}`)) ? 'light' : (isDragToggle && selected.has(`${turnIdx}`)) ? 'light' :
@@ -88,11 +112,13 @@ toggleTurn(...$event);
: 'primary' : 'primary'
" "
>{{ turnIdx + 1 }}</BButton> >{{ turnIdx + 1 }}</BButton>
<div v-else class="plain-center">{{ turnIdx + 1 }}</div>
</div> </div>
</DragSelect> </DragSelect>
<DragSelect <DragSelect
:style="rowGridStyle" :style="rowGridStyle"
attribute="turnIdx" attribute="turnIdx"
:disabled="!isEditMode"
@dragStart="isDragSingle = true" @dragStart="isDragSingle = true"
@dragDone=" @dragDone="
isDragSingle = false; isDragSingle = false;
@@ -158,10 +184,27 @@ selectTurn(...$event);
></span> ></span>
</div> </div>
</div> </div>
<div v-if="!isEditMode" :style="rowGridStyle">
<div
v-for="(turnObj, turnIdx) in reservedCommandList.slice(
0,
viewMaxTurn
)"
:key="turnIdx"
class="action_pad d-grid"
>
<BButton
:variant="(turnIdx % 2 == 0) ? 'secondary' : 'dark'"
size="sm"
class="simple_action_btn bi bi-pencil"
@click="toggleQuickReserveForm(turnIdx)"
></BButton>
</div>
</div>
</div> </div>
<div class="row gx-1"> <div class="row gx-1">
<div class="col d-grid"> <div class="col d-grid">
<BDropdown right split text="당기기" @click="pullGeneralCommandSingle"> <BDropdown text="당기기">
<BDropdownItem <BDropdownItem
v-for="turnIdx in maxPushTurn" v-for="turnIdx in maxPushTurn"
:key="turnIdx" :key="turnIdx"
@@ -170,7 +213,7 @@ selectTurn(...$event);
</BDropdown> </BDropdown>
</div> </div>
<div class="col d-grid"> <div class="col d-grid">
<BDropdown right split text="미루기" @click="pushGeneralCommandSingle"> <BDropdown text="미루기">
<BDropdownItem <BDropdownItem
v-for="turnIdx in maxPushTurn" v-for="turnIdx in maxPushTurn"
:key="turnIdx" :key="turnIdx"
@@ -193,6 +236,13 @@ selectTurn(...$event);
ref="commandSelectForm" ref="commandSelectForm"
@on-close="chooseCommand($event)" @on-close="chooseCommand($event)"
/> />
<CommandSelectForm
:commandList="commandList"
anchor=".commandQuickReserveFormAnchor"
ref="commandQuickReserveForm"
@on-close="chooseQuickReserveCommand($event)"
:hideClose="false"
/>
</template> </template>
<script lang="ts"> <script lang="ts">
@@ -276,11 +326,11 @@ for (const commandCategories of commandList) {
} }
} }
function toggleForm($event: Event): void{ function toggleForm($event: Event): void {
$event.preventDefault(); $event.preventDefault();
const form = commandSelectForm.value; const form = commandSelectForm.value;
if(!form){ if (!form) {
return; return;
} }
form.toggle(); form.toggle();
@@ -323,6 +373,7 @@ const emptyTurn: TurnObjWithTime[] = Array.from<TurnObjWithTime>({
const prevTurnList = ref(new Set([0])); const prevTurnList = ref(new Set([0]));
const turnList = ref(new Set<number>()); const turnList = ref(new Set<number>());
const reservedCommandList = ref(emptyTurn); const reservedCommandList = ref(emptyTurn);
const isEditMode = ref(false);
const flippedMaxTurn = 15; const flippedMaxTurn = 15;
const viewMaxTurn = ref(flippedMaxTurn); const viewMaxTurn = ref(flippedMaxTurn);
@@ -431,6 +482,7 @@ async function pushGeneralCommand(amount: number) {
await reloadCommandList(); await reloadCommandList();
} }
/*
function pushGeneralCommandSingle(e: Event) { function pushGeneralCommandSingle(e: Event) {
//NOTE: split 구현에 버그가 있어서, 수동으로 구분해야함 //NOTE: split 구현에 버그가 있어서, 수동으로 구분해야함
if (isDropdownChildren(e)) { if (isDropdownChildren(e)) {
@@ -446,6 +498,7 @@ function pullGeneralCommandSingle(e: Event) {
} }
void pushGeneralCommand(-1); void pushGeneralCommand(-1);
} }
*/
async function reloadCommandList() { async function reloadCommandList() {
let result: ReservedCommandResponse; let result: ReservedCommandResponse;
@@ -561,10 +614,42 @@ function chooseCommand(val?: string) {
selectedCommand.value = invCommandMap[val]; selectedCommand.value = invCommandMap[val];
} }
const commandQuickReserveForm = ref<InstanceType<typeof CommandSelectForm> | null>(null);
const currentQuickReserveTarget = ref(-1);
function chooseQuickReserveCommand(val?: string) {
if (!val) {
return;
}
selectedCommand.value = invCommandMap[val];
turnList.value.clear();
turnList.value.add(currentQuickReserveTarget.value);
void reserveCommand();
}
function toggleQuickReserveForm(turnIdx: number) {
if (turnIdx == currentQuickReserveTarget.value) {
commandQuickReserveForm.value?.toggle();
return;
}
currentQuickReserveTarget.value = turnIdx;
commandQuickReserveForm.value?.show();
}
onMounted(() => { onMounted(() => {
void reloadCommandList(); void reloadCommandList();
}); });
watch(isEditMode, newEditMode => {
if (newEditMode) {
commandQuickReserveForm.value?.close();
currentQuickReserveTarget.value = -1;
}
else {
commandSelectForm.value?.close();
}
});
</script> </script>
<style lang="scss"> <style lang="scss">
@use "sass:color"; @use "sass:color";
@@ -576,9 +661,19 @@ onMounted(() => {
.commandPad { .commandPad {
background-color: $gray-900; background-color: $gray-900;
position: relative;
} }
.commandTable { .commandTable {
width: 100%;
display: grid;
grid-template-columns:
minmax(20px, 0.8fr) minmax(75px, 2.4fr) minmax(40px, 0.9fr)
4.8fr minmax(28px, 0.8fr);
//30, 70, 37.65, 160
}
.commandTable.isEditMode {
width: 100%; width: 100%;
display: grid; display: grid;
grid-template-columns: minmax(30px, 1fr) minmax(75px, 2.5fr) minmax(40px, 1fr) 5fr; grid-template-columns: minmax(30px, 1fr) minmax(75px, 2.5fr) minmax(40px, 1fr) 5fr;
@@ -628,11 +723,16 @@ onMounted(() => {
} }
} }
.month_pad:hover { .isEditMode .month_pad:hover {
text-decoration: underline; text-decoration: underline;
cursor: pointer; cursor: pointer;
} }
.plain-center {
background-color: black;
}
.plain-center,
.month_pad, .month_pad,
.time_pad, .time_pad,
.turn_pad { .turn_pad {
+18 -3
View File
@@ -22,7 +22,17 @@
@click="close(commandItem.value)" @click="close(commandItem.value)"
> >
<div class="commandItem"> <div class="commandItem">
<p class="center my-0">{{ commandItem.simpleName }}</p> <p :class="['center', 'my-0', commandItem.possible ? '' : 'commandImpossible']">
{{ commandItem.simpleName }}
<span
class="compensatePositive"
v-if="commandItem.compensation > 0"
></span>
<span
class="compensateNegative"
v-else-if="commandItem.compensation < 0"
></span>
</p>
<small class="center" :style="{ display: 'block' }"> <small class="center" :style="{ display: 'block' }">
{{ {{
commandItem.title.startsWith(commandItem.simpleName) commandItem.title.startsWith(commandItem.simpleName)
@@ -33,11 +43,11 @@
</div> </div>
</div> </div>
</div> </div>
<!--<div class="commandBottom row mt-1 mb-1"> <div v-if="!hideClose" class="commandBottom row mt-1 mb-1">
<div class="offset-8 col-4 d-grid"> <div class="offset-8 col-4 d-grid">
<BButton @click="close()">닫기</BButton> <BButton @click="close()">닫기</BButton>
</div> </div>
</div>--> </div>
</div> </div>
</teleport> </teleport>
</template> </template>
@@ -86,6 +96,11 @@ const props = defineProps({
type: String, type: String,
required: false, required: false,
default: '.commandSelectFormAnchor', default: '.commandSelectFormAnchor',
},
hideClose: {
type: Boolean,
required: false,
default: true,
} }
}) })
+45 -11
View File
@@ -1,12 +1,14 @@
<template> <template>
<div <div
ref="container" ref="container"
style=" :style="{
position: relative; position: 'relative',
user-select: none; userSelect: disabled ? undefined : 'none',
overflow: hidden; overflow: 'hidden',
touch-action: none; touchAction: disabled ? undefined : 'none',
}
" "
:class="{ disabledDrag: disabled }"
> >
<slot :selected="intersected" /> <slot :selected="intersected" />
</div> </div>
@@ -58,6 +60,11 @@ export default defineComponent({
required: false, required: false,
default: () => ref(new Set()), default: () => ref(new Set()),
}, },
disabled: {
type: Boolean,
required: false,
default: false,
}
}, },
emits: ["update:modelValue", "dragDone", "dragStart"], emits: ["update:modelValue", "dragDone", "dragStart"],
setup(props, { emit }) { setup(props, { emit }) {
@@ -138,6 +145,9 @@ export default defineComponent({
let isMine = false; let isMine = false;
function startDrag(e: MouseEvent | Touch) { function startDrag(e: MouseEvent | Touch) {
if (props.disabled) {
return;
}
containerRect = uContainer.getBoundingClientRect(); containerRect = uContainer.getBoundingClientRect();
children = uContainer.children; children = uContainer.children;
start = getCoords(e); start = getCoords(e);
@@ -152,6 +162,9 @@ export default defineComponent({
emit("dragStart"); emit("dragStart");
} }
function drag(e: MouseEvent | Touch) { function drag(e: MouseEvent | Touch) {
if (props.disabled) {
return;
}
end = getCoords(e); end = getCoords(e);
const dimensions = getDimensions(start, end); const dimensions = getDimensions(start, end);
if (end.x < start.x) { if (end.x < start.x) {
@@ -165,6 +178,9 @@ export default defineComponent({
intersection(); intersection();
} }
function endDrag() { function endDrag() {
if (props.disabled) {
return;
}
start = { x: 0, y: 0 }; start = { x: 0, y: 0 };
end = { x: 0, y: 0 }; end = { x: 0, y: 0 };
box.style.width = "0"; box.style.width = "0";
@@ -172,16 +188,34 @@ export default defineComponent({
document.removeEventListener("mousemove", drag); document.removeEventListener("mousemove", drag);
document.removeEventListener("touchmove", touchMove); document.removeEventListener("touchmove", touchMove);
box.remove(); box.remove();
if(isMine){ if (isMine) {
emit("dragDone", intersected.value); emit("dragDone", intersected.value);
} }
isMine = false; isMine = false;
} }
uContainer.addEventListener("mousedown", startDrag); watch(() => props.disabled, disabledNext => {
uContainer.addEventListener("touchstart", touchStart); if (disabledNext) {
document.addEventListener("mouseup", endDrag); uContainer.removeEventListener("mousedown", startDrag);
document.addEventListener("touchend", endDrag); uContainer.removeEventListener("touchstart", touchStart);
document.removeEventListener("mouseup", endDrag);
document.removeEventListener("touchend", endDrag);
}
else {
uContainer.addEventListener("mousedown", startDrag);
uContainer.addEventListener("touchstart", touchStart);
document.addEventListener("mouseup", endDrag);
document.addEventListener("touchend", endDrag);
}
});
if (!props.disabled) {
uContainer.addEventListener("mousedown", startDrag);
uContainer.addEventListener("touchstart", touchStart);
document.addEventListener("mouseup", endDrag);
document.addEventListener("touchend", endDrag);
}
onBeforeUnmount(() => { onBeforeUnmount(() => {
uContainer.removeEventListener("mousedown", startDrag); uContainer.removeEventListener("mousedown", startDrag);