refactor invitation handling: remove email parameter from createInviteLink and update UI to use invite link
This commit is contained in:
parent
4edeb6dfe4
commit
e873bbc3f8
4 changed files with 19 additions and 73 deletions
|
|
@ -14,21 +14,13 @@ export async function acceptInvitation(token: string): Promise<Household> {
|
||||||
return { id: h.id, name: h.name, slug: h.slug }
|
return { id: h.id, name: h.name, slug: h.slug }
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function sendInvitation(householdSlug: string, email: string): Promise<void> {
|
export async function createInviteLink(householdSlug: string): Promise<string> {
|
||||||
const res = await api.POST('/api/v1/households/{householdSlug}/invitations', {
|
const { data, error, response } = await api.POST('/api/v1/households/{householdSlug}/invitations', { params: { path: { householdSlug } } })
|
||||||
params: { path: { householdSlug } },
|
|
||||||
body: { email },
|
|
||||||
})
|
|
||||||
if (!res.response.ok) throw new Error(`${res.response.status} ${res.response.statusText || 'HTTP error'}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function createInviteLink(householdSlug: string, email: string): Promise<string> {
|
if (!response.ok) {
|
||||||
const res = await api.POST('/api/v1/households/{householdSlug}/invitations', {
|
throw new Error(`${response.status} ${response.statusText || 'HTTP error'}${error ? `: ${String(error)}` : ''}`)
|
||||||
params: { path: { householdSlug } },
|
}
|
||||||
body: { email },
|
const inviteLink = data?.invite_link
|
||||||
})
|
|
||||||
if (!res.response.ok) throw new Error(`${res.response.status} ${res.response.statusText || 'HTTP error'}`)
|
|
||||||
const inviteLink = res.data?.invite_link
|
|
||||||
if (typeof inviteLink !== 'string') throw new Error('Invalid response: missing invite_link')
|
if (typeof inviteLink !== 'string') throw new Error('Invalid response: missing invite_link')
|
||||||
return inviteLink
|
return inviteLink
|
||||||
}
|
}
|
||||||
|
|
@ -462,11 +462,6 @@ export interface components {
|
||||||
/** Name */
|
/** Name */
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
/** CreateInvitationBody */
|
|
||||||
CreateInvitationBody: {
|
|
||||||
/** Email */
|
|
||||||
email: string;
|
|
||||||
};
|
|
||||||
/** CurrentShoppingList */
|
/** CurrentShoppingList */
|
||||||
CurrentShoppingList: {
|
CurrentShoppingList: {
|
||||||
/** Outstandingitems */
|
/** Outstandingitems */
|
||||||
|
|
@ -1341,11 +1336,7 @@ export interface operations {
|
||||||
};
|
};
|
||||||
cookie?: never;
|
cookie?: never;
|
||||||
};
|
};
|
||||||
requestBody: {
|
requestBody?: never;
|
||||||
content: {
|
|
||||||
"application/json": components["schemas"]["CreateInvitationBody"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
responses: {
|
responses: {
|
||||||
/** @description Successful Response */
|
/** @description Successful Response */
|
||||||
200: {
|
200: {
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,7 @@
|
||||||
<h1>Household Members</h1>
|
<h1>Household Members</h1>
|
||||||
<section>
|
<section>
|
||||||
<h2>Invite a member</h2>
|
<h2>Invite a member</h2>
|
||||||
<form @submit.prevent="onInvite">
|
<p class="muted">Share an invite link with the person you want to add.</p>
|
||||||
<label for="email">Email</label>
|
|
||||||
<input
|
|
||||||
id="email"
|
|
||||||
v-model="email"
|
|
||||||
type="email"
|
|
||||||
required
|
|
||||||
autocomplete="email"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
:disabled="submitting"
|
|
||||||
>
|
|
||||||
Send Invitation
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
:disabled="submitting"
|
:disabled="submitting"
|
||||||
|
|
@ -25,7 +11,6 @@
|
||||||
>
|
>
|
||||||
Copy Invite Link
|
Copy Invite Link
|
||||||
</button>
|
</button>
|
||||||
</form>
|
|
||||||
<p
|
<p
|
||||||
v-if="message"
|
v-if="message"
|
||||||
class="message"
|
class="message"
|
||||||
|
|
@ -62,12 +47,11 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, computed } from 'vue'
|
import { ref, onMounted, computed } from 'vue'
|
||||||
import { sendInvitation, createInviteLink } from '@/api/invitations'
|
import { createInviteLink } from '@/api/invitations'
|
||||||
import { listMembers, type Member } from '@/api/households'
|
import { listMembers, type Member } from '@/api/households'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { useAlert } from '@/composables/useAlert'
|
import { useAlert } from '@/composables/useAlert'
|
||||||
|
|
||||||
const email = ref('')
|
|
||||||
const submitting = ref(false)
|
const submitting = ref(false)
|
||||||
const message = ref('')
|
const message = ref('')
|
||||||
const error = ref('')
|
const error = ref('')
|
||||||
|
|
@ -84,23 +68,6 @@ onMounted(async () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
async function onInvite() {
|
|
||||||
message.value = ''
|
|
||||||
error.value = ''
|
|
||||||
submitting.value = true
|
|
||||||
try {
|
|
||||||
const slug = householdSlug.value
|
|
||||||
if (!slug) throw new Error('No household selected')
|
|
||||||
await sendInvitation(slug, email.value.trim())
|
|
||||||
message.value = 'Invitation sent.'
|
|
||||||
email.value = ''
|
|
||||||
} catch (e) {
|
|
||||||
error.value = e instanceof Error ? e.message : 'Failed to send invitation'
|
|
||||||
} finally {
|
|
||||||
submitting.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onCopyInviteLink() {
|
async function onCopyInviteLink() {
|
||||||
message.value = ''
|
message.value = ''
|
||||||
error.value = ''
|
error.value = ''
|
||||||
|
|
@ -108,15 +75,11 @@ async function onCopyInviteLink() {
|
||||||
try {
|
try {
|
||||||
const slug = householdSlug.value
|
const slug = householdSlug.value
|
||||||
if (!slug) throw new Error('No household selected')
|
if (!slug) throw new Error('No household selected')
|
||||||
const emailValue = email.value.trim()
|
const inviteLink = await createInviteLink(slug)
|
||||||
if (!emailValue) throw new Error('Please enter an email address')
|
|
||||||
|
|
||||||
const inviteLink = await createInviteLink(slug, emailValue)
|
|
||||||
await navigator.clipboard.writeText(inviteLink)
|
await navigator.clipboard.writeText(inviteLink)
|
||||||
|
|
||||||
showAlert({ type: 'success', heading: 'Success', message: 'Invite link copied to clipboard!' })
|
showAlert({ type: 'success', heading: 'Success', message: 'Invite link copied to clipboard!' })
|
||||||
scheduleAutoDismiss(3000)
|
scheduleAutoDismiss(3000)
|
||||||
email.value = ''
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error.value = e instanceof Error ? e.message : 'Failed to copy invite link'
|
error.value = e instanceof Error ? e.message : 'Failed to copy invite link'
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<h2>Join an existing household</h2>
|
<h2>Join an existing household</h2>
|
||||||
<p>To join a household, ask an existing member to send an invitation to your email address.</p>
|
<p>To join a household, ask an existing member to share an invitation link with you.</p>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue