refactor: refactor create team modal to new system

This commit is contained in:
Andrew Bastin
2021-10-01 22:41:30 +05:30
committed by liyasthomas
parent 079083d0f2
commit 7ab1bbaf62
4 changed files with 100 additions and 55 deletions

View File

@@ -1,5 +1,5 @@
<template> <template>
<SmartModal v-if="show" :title="$t('team.new')" @close="hideModal"> <SmartModal v-if="show" :title="$t('team.new').toString()" @close="hideModal">
<template #body> <template #body>
<div class="flex flex-col px-2"> <div class="flex flex-col px-2">
<input <input
@@ -19,9 +19,12 @@
</template> </template>
<template #footer> <template #footer>
<span> <span>
<ButtonPrimary :label="$t('action.save')" @click.native="addNewTeam" /> <ButtonPrimary
:label="$t('action.save').toString()"
@click.native="addNewTeam"
/>
<ButtonSecondary <ButtonSecondary
:label="$t('action.cancel')" :label="$t('action.cancel').toString()"
@click.native="hideModal" @click.native="hideModal"
/> />
</span> </span>
@@ -29,54 +32,56 @@
</SmartModal> </SmartModal>
</template> </template>
<script> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api" import { ref, useContext } from "@nuxtjs/composition-api"
import * as teamUtils from "~/helpers/teams/utils" import { pipe } from "fp-ts/function"
import * as TE from "fp-ts/TaskEither"
import { createTeam } from "~/helpers/backend/mutations/Team"
import { TeamNameCodec } from "~/helpers/backend/types/TeamName"
export default defineComponent({ const {
props: { app: { i18n },
show: Boolean, $toast,
}, } = useContext()
data() {
return { const $t = i18n.t.bind(i18n)
name: null,
} defineProps<{
}, show: boolean
methods: { }>()
addNewTeam() {
// We save the user input in case of an error const emit = defineEmits<{
const name = this.name (e: "hide-modal"): void
// We clear it early to give the UI a snappy feel }>()
this.name = ""
if (!name) { const name = ref<string | null>(null)
this.$toast.error(this.$t("empty.team_name"), {
icon: "error_outline", const addNewTeam = () =>
}) pipe(
return TeamNameCodec.decode(name.value), // Perform decode (returns either)
TE.fromEither, // Convert either to a task either
TE.mapLeft(() => "invalid_name" as const), // Failure above is an invalid_name, give it an identifiable value
TE.chainW(createTeam), // Create the team
TE.match(
(err) => {
// err is of type "invalid_name" | GQLError<Err>
if (err === "invalid_name") {
$toast.error($t("team.name_length_insufficient").toString(), {
icon: "error_outline",
})
} else {
// Handle GQL errors (use err obj)
}
},
() => {
// Success logic ?
hideModal()
} }
if (name !== null && name.replace(/\s/g, "").length < 6) { )
this.$toast.error(this.$t("team.name_length_insufficient"), { )()
icon: "error_outline",
}) const hideModal = () => {
return name.value = null
} emit("hide-modal")
// Call to the graphql mutation }
teamUtils
.createTeam(this.$apollo, name)
.then(() => {
this.hideModal()
})
.catch((e) => {
console.error(e)
// We restore the initial user input
this.name = name
})
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
})
</script> </script>

View File

@@ -4,7 +4,7 @@
<div class="p-4"> <div class="p-4">
<label <label
class="cursor-pointer transition hover:text-secondaryDark" class="cursor-pointer transition hover:text-secondaryDark"
@click="team.myRole === 'OWNER' ? $emit('edit-team') : ''" @click="team.myRole === 'OWNER' ? emit('edit-team') : ''"
> >
{{ team.name || $t("state.nothing_found") }} {{ team.name || $t("state.nothing_found") }}
</label> </label>
@@ -36,7 +36,7 @@
:label="$t('action.edit').toString()" :label="$t('action.edit').toString()"
@click.native=" @click.native="
() => { () => {
$emit('edit-team') emit('edit-team')
$refs.options.tippy().hide() $refs.options.tippy().hide()
} }
" "
@@ -94,6 +94,11 @@ const props = defineProps<{
teamID: string teamID: string
}>() }>()
const emit = defineEmits<{
(e: "edit-team"): void
}>()
const { const {
app: { i18n }, app: { i18n },
$toast, $toast,

View File

@@ -1,12 +1,47 @@
import gql from "graphql-tag" import gql from "graphql-tag"
import { pipe } from "fp-ts/function"
import * as TE from "fp-ts/TaskEither"
import { runMutation } from "../GQLClient" import { runMutation } from "../GQLClient"
import { TeamName } from "../types/TeamName"
type DeleteTeamErrors = type DeleteTeamErrors =
| "team/not_required_role" | "team/not_required_role"
| "team/invalid_id" | "team/invalid_id"
| "team/member_not_found" | "team/member_not_found"
| "ea/not_invite_or_admin"
type ExitTeamErrors = "team/invalid_id" | "team/member_not_found" type ExitTeamErrors =
| "team/invalid_id"
| "team/member_not_found"
| "ea/not_invite_or_admin"
type CreateTeamErrors = "team/name_invalid" | "ea/not_invite_or_admin"
export const createTeam = (name: TeamName) =>
pipe(
runMutation<
{
createTeam: {
id: string
name: string
}
},
CreateTeamErrors
>(
gql`
mutation CreateTeam($name: String!) {
createTeam(name: $name) {
id
name
}
}
`,
{
name,
}
),
TE.map(({ createTeam }) => createTeam)
)
export const deleteTeam = (teamID: string) => export const deleteTeam = (teamID: string) =>
runMutation<void, DeleteTeamErrors>( runMutation<void, DeleteTeamErrors>(

View File

@@ -6,7 +6,7 @@ interface TeamNameBrand {
export const TeamNameCodec = t.brand( export const TeamNameCodec = t.brand(
t.string, t.string,
(x): x is t.Branded<string, TeamNameBrand> => x.length > 6, (x): x is t.Branded<string, TeamNameBrand> => x.trim().length > 6,
"TeamName" "TeamName"
) )