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>
<SmartModal v-if="show" :title="$t('team.new')" @close="hideModal">
<SmartModal v-if="show" :title="$t('team.new').toString()" @close="hideModal">
<template #body>
<div class="flex flex-col px-2">
<input
@@ -19,9 +19,12 @@
</template>
<template #footer>
<span>
<ButtonPrimary :label="$t('action.save')" @click.native="addNewTeam" />
<ButtonPrimary
:label="$t('action.save').toString()"
@click.native="addNewTeam"
/>
<ButtonSecondary
:label="$t('action.cancel')"
:label="$t('action.cancel').toString()"
@click.native="hideModal"
/>
</span>
@@ -29,54 +32,56 @@
</SmartModal>
</template>
<script>
import { defineComponent } from "@nuxtjs/composition-api"
import * as teamUtils from "~/helpers/teams/utils"
<script setup lang="ts">
import { ref, useContext } from "@nuxtjs/composition-api"
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({
props: {
show: Boolean,
},
data() {
return {
name: null,
}
},
methods: {
addNewTeam() {
// We save the user input in case of an error
const name = this.name
// We clear it early to give the UI a snappy feel
this.name = ""
if (!name) {
this.$toast.error(this.$t("empty.team_name"), {
icon: "error_outline",
})
return
const {
app: { i18n },
$toast,
} = useContext()
const $t = i18n.t.bind(i18n)
defineProps<{
show: boolean
}>()
const emit = defineEmits<{
(e: "hide-modal"): void
}>()
const name = ref<string | null>(null)
const addNewTeam = () =>
pipe(
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",
})
return
}
// 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")
},
},
})
)
)()
const hideModal = () => {
name.value = null
emit("hide-modal")
}
</script>

View File

@@ -4,7 +4,7 @@
<div class="p-4">
<label
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") }}
</label>
@@ -36,7 +36,7 @@
:label="$t('action.edit').toString()"
@click.native="
() => {
$emit('edit-team')
emit('edit-team')
$refs.options.tippy().hide()
}
"
@@ -94,6 +94,11 @@ const props = defineProps<{
teamID: string
}>()
const emit = defineEmits<{
(e: "edit-team"): void
}>()
const {
app: { i18n },
$toast,

View File

@@ -1,12 +1,47 @@
import gql from "graphql-tag"
import { pipe } from "fp-ts/function"
import * as TE from "fp-ts/TaskEither"
import { runMutation } from "../GQLClient"
import { TeamName } from "../types/TeamName"
type DeleteTeamErrors =
| "team/not_required_role"
| "team/invalid_id"
| "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) =>
runMutation<void, DeleteTeamErrors>(

View File

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