refactor: refactor create team modal to new system
This commit is contained in:
committed by
liyasthomas
parent
079083d0f2
commit
7ab1bbaf62
@@ -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>
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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>(
|
||||||
|
|||||||
@@ -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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user