Files
webapp/app/pages/clientarea/company-switch.vue
2026-01-07 09:10:35 +07:00

161 lines
5.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<Section variant="plain">
<Stack gap="6">
<Stack gap="2">
<Heading :level="1">{{ $t('dashboard.switch_company') }}</Heading>
<Text tone="muted" size="base">{{ $t('teams.switch_description') }}</Text>
</Stack>
<Alert v-if="hasError" variant="error">
<Stack gap="2">
<Heading :level="4" weight="semibold">{{ $t('common.error') }}</Heading>
<Text tone="muted">{{ error }}</Text>
<Button @click="loadUserTeams">{{ t('clientTeam.error.retry') }}</Button>
</Stack>
</Alert>
<Card v-else-if="isLoading" tone="muted" padding="lg">
<Stack align="center" justify="center" gap="3">
<Spinner />
<Text tone="muted">{{ t('clientTeamSwitch.loading.message') }}</Text>
</Stack>
</Card>
<Card v-else-if="!userTeams.length && !showCreateForm" padding="lg">
<Stack align="center" gap="3">
<IconCircle tone="primary">🏢</IconCircle>
<Heading :level="3" align="center">{{ $t('teams.no_team') }}</Heading>
<Text tone="muted" align="center">{{ $t('teams.no_team_description') }}</Text>
<Button @click="showCreateForm = true">
{{ $t('teams.create_first_team') }}
</Button>
</Stack>
</Card>
<template v-else>
<Grid :cols="1" :md="2" :lg="3" :gap="4" v-if="!showCreateForm">
<Card
v-for="team in userTeams"
:key="team.id"
padding="lg"
:class="[
'cursor-pointer transition-all',
team.isActive ? 'ring-2 ring-primary bg-primary/5' : 'hover:shadow-md'
]"
@click="switchToTeam(team.id)"
>
<Stack gap="3">
<Stack direction="row" gap="3" align="center">
<IconCircle :tone="team.isActive ? 'primary' : 'neutral'">
{{ team.name?.charAt(0)?.toUpperCase() || '?' }}
</IconCircle>
<Stack gap="1">
<Heading :level="4" weight="semibold">{{ team.name }}</Heading>
</Stack>
</Stack>
<Pill v-if="team.isActive" variant="primary">{{ $t('teams.active') }}</Pill>
</Stack>
</Card>
<Card padding="lg" class="border-2 border-dashed border-base-300 hover:border-primary cursor-pointer transition-colors" @click="showCreateForm = true">
<Stack align="center" gap="3">
<IconCircle tone="neutral"></IconCircle>
<Heading :level="4" weight="semibold">{{ $t('teams.create_new_team') }}</Heading>
<Text tone="muted" align="center">{{ $t('teams.create_description') }}</Text>
</Stack>
</Card>
</Grid>
<TeamCreateForm
v-else
@team-created="handleTeamCreated"
@cancel="showCreateForm = false"
/>
</template>
</Stack>
</Section>
</template>
<script setup lang="ts">
import { SwitchTeamDocument } from '~/composables/graphql/user/teams-generated'
definePageMeta({
middleware: ['auth-oidc']
})
const localePath = useLocalePath()
const { t } = useI18n()
const { mutate } = useGraphQL()
const { setActiveTeam } = useActiveTeam()
const me = useState<{
teams?: Array<{ id?: string | null; name: string; logtoOrgId?: string | null } | null> | null
activeTeamId?: string | null
} | null>('me', () => null)
const userTeams = ref<Array<{ id: string; name: string; logtoOrgId?: string | null; isActive?: boolean }>>([])
const isLoading = ref(true)
const hasError = ref(false)
const error = ref('')
const showCreateForm = ref(false)
const currentActiveTeam = computed(() => userTeams.value.find(team => team.isActive) || null)
const otherTeams = computed(() => userTeams.value.filter(team => !team.isActive))
const markActiveTeam = (teamId: string) => {
if (me.value) {
me.value = { ...me.value, activeTeamId: teamId }
}
userTeams.value = userTeams.value.map(team => ({
...team,
isActive: team.id === teamId
}))
}
const loadUserTeams = () => {
isLoading.value = true
hasError.value = false
if (!me.value?.teams) {
hasError.value = true
error.value = t('clientTeamSwitch.error.load')
isLoading.value = false
return
}
userTeams.value = me.value.teams
.filter((t): t is NonNullable<typeof t> => t !== null)
.map(t => ({
id: t.id || '',
name: t.name,
logtoOrgId: t.logtoOrgId,
isActive: t.id === me.value?.activeTeamId
}))
isLoading.value = false
}
const switchToTeam = async (teamId: string) => {
try {
const selectedTeam = userTeams.value.find(team => team.id === teamId)
if (selectedTeam) setActiveTeam(teamId, selectedTeam.logtoOrgId)
const result = await mutate(SwitchTeamDocument, { teamId }, 'user', 'teams')
if (result.switchTeam?.user) {
const newActiveId = result.switchTeam.user.activeTeamId || teamId
setActiveTeam(newActiveId, selectedTeam?.logtoOrgId)
markActiveTeam(newActiveId)
navigateTo(localePath('/clientarea/team'))
}
} catch (err: any) {
error.value = err.message || t('clientTeamSwitch.error.switch')
hasError.value = true
}
}
const handleTeamCreated = () => {
showCreateForm.value = false
navigateTo(localePath('/clientarea/team'))
}
loadUserTeams()
</script>