Skip to content

Commit

Permalink
Fb/step create/edit with post time (#236)
Browse files Browse the repository at this point in the history
* starty start

* starty start 2

* starty start 3

* starty start 4

* starty start 5

* nicer dicer 1

* nicer dicer 2

* nicer dicer 3

* nicer dicer 4

* ui consistency
  • Loading branch information
rlindner81 committed Jan 15, 2024
1 parent 26cc3b2 commit b9534dc
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 14 deletions.
44 changes: 41 additions & 3 deletions frontend/src/components/AddOrEditStep.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<script setup lang="ts">
import { computed, watch } from "vue";
import { computed, reactive, watch } from "vue";
import { TRACK_FIELD_INPUT, TRACK_FIELD_TYPE } from "@/constants";
import { useTrackStore } from "@/store/track";
import { useStepStore } from "@/store/step";
import { dateToEditableTime, editableTimeToDate, isEditableTime } from "@/datetime";
const trackStore = useTrackStore();
const stepStore = useStepStore();
Expand All @@ -27,12 +28,29 @@ const emit = defineEmits(["close"]);
const show = computed(() => props.show);
watch(show, (newValue) => {
if (newValue && !props.edit) {
stepStore.resetActiveStep();
if (newValue) {
activeStepPostedAtEditable.value = stepStore.activeStepPostedAt
? dateToEditableTime(stepStore.activeStepPostedAt)
: dateToEditableTime(new Date());
if (!props.edit) {
stepStore.resetActiveStep();
}
}
});
const activeStepPostedAtEditable = defineModel<string>();
const activeStepPostedAtEditableRules = reactive([(value) => isEditableTime(value) || "Enter a valid time."]);
const onCreateOrUpdate = async () => {
if (stepStore.activeStepPostedAtEnabled && activeStepPostedAtEditable.value) {
if (!isEditableTime(activeStepPostedAtEditable.value)) {
// NOTE: cannot accept submission if postedAt is enabled, but not valid
return;
} else {
stepStore.activeStepPostedAt = editableTimeToDate(activeStepPostedAtEditable.value);
}
}
emit("close");
if (props.edit) {
await stepStore.updateStep();
Expand All @@ -52,6 +70,26 @@ const onClose = async () => {
<v-card-title class="text-h5">{{ edit ? $t("entity.step.edit") : $t("entity.step.add") }}</v-card-title>
<!-- TODO v-else would be nice-->
<v-container v-if="trackStore.current && stepStore.activeStepValues && stepStore.activeStepEnabled">
<v-row align="center">
<v-col cols="2" xs="1" sm="1">
<div>
<v-checkbox v-model="stepStore.activeStepPostedAtEnabled" color="secondary" />
</div>
</v-col>
<v-col>
<div>
<label :class="stepStore.activeStepPostedAtEnabled ? '' : 'disable'">Tracked On</label>
<v-text-field
v-model="activeStepPostedAtEditable"
:rules="activeStepPostedAtEditableRules"
:disabled="!stepStore.activeStepPostedAtEnabled"
density="compact"
hide-details="auto"
/>
</div>
</v-col>
</v-row>

<v-row align="center" v-for="(field, fieldIndex) in trackStore.current.fields" :key="fieldIndex">
<v-col cols="2" xs="1" sm="1">
<div v-if="trackStore.current.fields.some(({ optional }) => optional)">
Expand Down
26 changes: 26 additions & 0 deletions frontend/src/datetime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,29 @@ export const readableRelativeDateTime = (value: Date, now: Date = new Date()): s
: relativeDateTime;
}
};

const editableTimeRe = /^(\d\d).(\d\d).(\d\d\d\d) \| (\d\d):(\d\d)$/;

export const dateToEditableTime = (value: Date): string => {
if (!value) {
return "";
}
const day = _leadingZero2(value.getDate());
const month = _leadingZero2(value.getMonth() + 1);
const year = value.getFullYear();
const hour = _leadingZero2(value.getHours());
const minute = _leadingZero2(value.getMinutes());
return `${day}.${month}.${year} | ${hour}:${minute}`;
};

export const editableTimeToDate = (value: string): Date => {
if (!value) {
return new Date();
}
const [match, dayIn, monthIn, yearIn, hourIn, minuteIn] = editableTimeRe.exec(value) ?? [];
return match
? new Date(parseInt(yearIn), parseInt(monthIn) - 1, parseInt(dayIn), parseInt(hourIn), parseInt(minuteIn))
: new Date();
};

export const isEditableTime = (value: any): boolean => typeof value === "string" && editableTimeRe.test(value);
7 changes: 4 additions & 3 deletions frontend/src/firebase/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,13 @@ export const subscribeToSteps = async (userId, trackId, callback) => {
});
};

export const createStep = async (userId, trackId, step) => {
export const createStep = async (userId, trackId, step, postedAt: Date | null = null) => {
if (!userId || !trackId || !step) return;
const now = new Date();
await addDoc(stepsRef, {
...step,
posted_by: userId,
posted_at: now, // TODO this should be changeable in UI
posted_at: postedAt ?? now,
track_id: trackId,
_created_at: now,
_created_by: userId,
Expand All @@ -186,14 +186,15 @@ export const createStep = async (userId, trackId, step) => {
});
};

export const updateStep = async (userId, trackId, stepId, step) => {
export const updateStep = async (userId, trackId, stepId, step, postedAt: Date | null = null) => {
if (!userId || !trackId || !stepId || !step) return;
const now = new Date();
const stepRef = doc(stepsRef, stepId);
// NOTE: updateDoc will overwrite deep values, which is what we want here. Alternatively we could persist the
// enabled map alongside the values map. That would be cleaner we could setDoc again.
await updateDoc(stepRef, {
...step,
...((postedAt && { posted_at: postedAt }) ?? {}),
_updated_at: now,
_updated_by: userId,
});
Expand Down
34 changes: 26 additions & 8 deletions frontend/src/store/step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ interface State {
activeStepId: string | null;
activeStepValues: {} | null;
activeStepEnabled: {} | null;
activeStepPostedAt: Date | null;
activeStepPostedAtEnabled: boolean;
}

const _getSelectDefaultChoice = (field) => {
Expand Down Expand Up @@ -84,6 +86,8 @@ export const useStepStore = defineStore("step", {
activeStepId: null,
activeStepValues: null,
activeStepEnabled: null,
activeStepPostedAt: null,
activeStepPostedAtEnabled: false,
}),
getters: {
stepsDisplayRows(state) {
Expand Down Expand Up @@ -127,9 +131,15 @@ export const useStepStore = defineStore("step", {
if (!fields) {
this.activeStepValues = null;
this.activeStepEnabled = null;
this.activeStepPostedAt = null;
this.activeStepPostedAtEnabled = false;
return;
}
const activeStepId = input._id ?? null;

this.activeStepId = input._id ?? null;
this.activeStepPostedAt = input.posted_at ?? null;
this.activeStepPostedAtEnabled = false;

const activeStepValues = {};
const activeStepEnabled = {};

Expand All @@ -148,7 +158,6 @@ export const useStepStore = defineStore("step", {
}
}

this.activeStepId = activeStepId;
this.activeStepValues = activeStepValues;
this.activeStepEnabled = activeStepEnabled;
},
Expand All @@ -160,14 +169,23 @@ export const useStepStore = defineStore("step", {
this.setSteps([]);
},
async createStep() {
await createStep(useCommonStore().userId, useTrackStore().currentId, {
values: _filterDisabled(toRaw(this.activeStepEnabled), toRaw(this.activeStepValues)),
});
const step = { values: _filterDisabled(toRaw(this.activeStepEnabled), toRaw(this.activeStepValues)) };
await createStep(
useCommonStore().userId,
useTrackStore().currentId,
step,
this.activeStepPostedAtEnabled ? this.activeStepPostedAt : null,
);
},
async updateStep() {
await updateStep(useCommonStore().userId, useTrackStore().currentId, this.activeStepId, {
values: _filterDisabled(toRaw(this.activeStepEnabled), toRaw(this.activeStepValues)),
});
const step = { values: _filterDisabled(toRaw(this.activeStepEnabled), toRaw(this.activeStepValues)) };
await updateStep(
useCommonStore().userId,
useTrackStore().currentId,
this.activeStepId,
step,
this.activeStepPostedAtEnabled ? this.activeStepPostedAt : null,
);
},
},
});

0 comments on commit b9534dc

Please sign in to comment.