Refine comm event composer to keep fixed height and auto-close plus menu
This commit is contained in:
125
Frontend/app.vue
125
Frontend/app.vue
@@ -1694,6 +1694,7 @@ const commDraft = ref("");
|
||||
const commSending = ref(false);
|
||||
const commRecording = ref(false);
|
||||
const commComposerMode = ref<"message" | "planned" | "logged">("message");
|
||||
const commQuickMenuOpen = ref(false);
|
||||
const commEventSaving = ref(false);
|
||||
const commEventError = ref("");
|
||||
const commEventMode = ref<"planned" | "logged">("planned");
|
||||
@@ -1725,6 +1726,7 @@ watch(selectedCommThreadId, () => {
|
||||
commPinnedOnly.value = false;
|
||||
commDraft.value = "";
|
||||
commComposerMode.value = "message";
|
||||
commQuickMenuOpen.value = false;
|
||||
commEventError.value = "";
|
||||
eventCloseOpen.value = {};
|
||||
eventCloseDraft.value = {};
|
||||
@@ -2373,12 +2375,23 @@ function openCommEventModal(mode: "planned" | "logged") {
|
||||
setDefaultCommEventForm(mode);
|
||||
commEventError.value = "";
|
||||
commComposerMode.value = mode;
|
||||
commQuickMenuOpen.value = false;
|
||||
}
|
||||
|
||||
function closeCommEventModal() {
|
||||
if (commEventSaving.value) return;
|
||||
commComposerMode.value = "message";
|
||||
commEventError.value = "";
|
||||
commQuickMenuOpen.value = false;
|
||||
}
|
||||
|
||||
function toggleCommQuickMenu() {
|
||||
if (!selectedCommThread.value || commEventSaving.value) return;
|
||||
commQuickMenuOpen.value = !commQuickMenuOpen.value;
|
||||
}
|
||||
|
||||
function closeCommQuickMenu() {
|
||||
commQuickMenuOpen.value = false;
|
||||
}
|
||||
|
||||
function commComposerPlaceholder() {
|
||||
@@ -3666,11 +3679,17 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
|
||||
<div class="sticky bottom-0 z-10 mt-0 border-t border-base-300 bg-base-100/95 px-3 pt-3 backdrop-blur">
|
||||
<div class="absolute left-1/2 top-0 z-20 -translate-x-1/2 -translate-y-1/2">
|
||||
<div class="dropdown dropdown-top dropdown-center">
|
||||
<div
|
||||
class="dropdown dropdown-top dropdown-center"
|
||||
:class="{ 'dropdown-open': commQuickMenuOpen }"
|
||||
@focusout="closeCommQuickMenu"
|
||||
>
|
||||
<button
|
||||
tabindex="0"
|
||||
type="button"
|
||||
class="btn btn-sm btn-circle border border-base-300 bg-base-100 text-base-content/85 hover:bg-base-200"
|
||||
title="Add event"
|
||||
@click.stop="toggleCommQuickMenu"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
@@ -3690,19 +3709,6 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
</div>
|
||||
<div class="comm-input-wrap">
|
||||
<div class="comm-input-shell">
|
||||
<div v-if="commComposerMode !== 'message'" class="mb-2 flex items-center justify-between gap-2">
|
||||
<p class="text-xs font-medium text-base-content/75">
|
||||
{{ commComposerMode === "logged" ? "Log past event" : "Plan event" }}
|
||||
</p>
|
||||
<button
|
||||
class="btn btn-ghost btn-xs h-6 min-h-6 px-2"
|
||||
:disabled="commEventSaving"
|
||||
@click="closeCommEventModal"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
v-model="commDraft"
|
||||
class="comm-input-textarea"
|
||||
@@ -3713,43 +3719,34 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
|
||||
<div
|
||||
v-if="commComposerMode !== 'message'"
|
||||
class="mb-2 grid grid-cols-1 gap-2 sm:grid-cols-3"
|
||||
class="comm-event-controls"
|
||||
>
|
||||
<label class="form-control">
|
||||
<span class="label-text text-[11px]">Date</span>
|
||||
<input
|
||||
v-model="commEventForm.startDate"
|
||||
type="date"
|
||||
class="input input-bordered input-sm"
|
||||
:disabled="commEventSaving"
|
||||
>
|
||||
</label>
|
||||
<label class="form-control">
|
||||
<span class="label-text text-[11px]">Time</span>
|
||||
<input
|
||||
v-model="commEventForm.startTime"
|
||||
type="time"
|
||||
class="input input-bordered input-sm"
|
||||
:disabled="commEventSaving"
|
||||
>
|
||||
</label>
|
||||
<label class="form-control">
|
||||
<span class="label-text text-[11px]">Duration</span>
|
||||
<select
|
||||
v-model.number="commEventForm.durationMinutes"
|
||||
class="select select-bordered select-sm"
|
||||
:disabled="commEventSaving"
|
||||
>
|
||||
<option :value="15">15 min</option>
|
||||
<option :value="30">30 min</option>
|
||||
<option :value="45">45 min</option>
|
||||
<option :value="60">60 min</option>
|
||||
<option :value="90">90 min</option>
|
||||
</select>
|
||||
</label>
|
||||
<input
|
||||
v-model="commEventForm.startDate"
|
||||
type="date"
|
||||
class="input input-bordered input-xs h-7 min-h-7"
|
||||
:disabled="commEventSaving"
|
||||
>
|
||||
<input
|
||||
v-model="commEventForm.startTime"
|
||||
type="time"
|
||||
class="input input-bordered input-xs h-7 min-h-7"
|
||||
:disabled="commEventSaving"
|
||||
>
|
||||
<select
|
||||
v-model.number="commEventForm.durationMinutes"
|
||||
class="select select-bordered select-xs h-7 min-h-7"
|
||||
:disabled="commEventSaving"
|
||||
>
|
||||
<option :value="15">15m</option>
|
||||
<option :value="30">30m</option>
|
||||
<option :value="45">45m</option>
|
||||
<option :value="60">60m</option>
|
||||
<option :value="90">90m</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<p v-if="commEventError && commComposerMode !== 'message'" class="mb-2 text-xs text-error">
|
||||
<p v-if="commEventError && commComposerMode !== 'message'" class="comm-event-error text-xs text-error">
|
||||
{{ commEventError }}
|
||||
</p>
|
||||
|
||||
@@ -3776,6 +3773,17 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
</div>
|
||||
|
||||
<div class="comm-input-actions">
|
||||
<button
|
||||
v-if="commComposerMode !== 'message'"
|
||||
class="btn btn-xs btn-circle border border-base-300 bg-base-100 text-base-content/80 hover:bg-base-200"
|
||||
:disabled="commEventSaving"
|
||||
title="Back to message"
|
||||
@click="closeCommEventModal"
|
||||
>
|
||||
<svg viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
|
||||
<path d="M20 11H7.83l4.58-4.59L11 5l-7 7 7 7 1.41-1.41L7.83 13H20z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-xs btn-circle border border-base-300 bg-base-100 text-base-content/80 hover:bg-base-200"
|
||||
:class="commRecording ? 'comm-mic-active' : ''"
|
||||
@@ -4149,6 +4157,27 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.comm-event-controls {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
bottom: 8px;
|
||||
display: grid;
|
||||
grid-template-columns: 118px 88px 64px;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.comm-event-controls :is(input, select) {
|
||||
font-size: 11px;
|
||||
padding-inline: 8px;
|
||||
}
|
||||
|
||||
.comm-event-error {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
.comm-input-textarea::placeholder {
|
||||
color: color-mix(in oklab, var(--color-base-content) 45%, transparent);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user