refactor components and notifications bug
This commit is contained in:
43
CHANGELOG.md
43
CHANGELOG.md
@@ -1,19 +1,30 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Version 1.4.1
|
||||||
|
|
||||||
|
- Refactor some components and explicitly split out client only components
|
||||||
|
- Fix bug in the notifications
|
||||||
|
- Update readme to indicate sister project in react/next
|
||||||
|
|
||||||
## Version 1.4.0
|
## Version 1.4.0
|
||||||
|
|
||||||
- Cookie Consent
|
- Cookie Consent
|
||||||
```npm i vanilla-cookieconsent```
|
`npm i vanilla-cookieconsent`
|
||||||
|
|
||||||
## Version 1.3.0
|
## Version 1.3.0
|
||||||
|
|
||||||
- Add an example of usage limits (Notes AI Gen).
|
- Add an example of usage limits (Notes AI Gen).
|
||||||
- Includes non-destructive schema changes
|
- Includes non-destructive schema changes
|
||||||
```npx prisma db push```
|
`npx prisma db push`
|
||||||
|
|
||||||
## Version 1.2.0
|
## Version 1.2.0
|
||||||
|
|
||||||
- 'Lift' auth context into server middleware to support authenticated api (rest) endpoints for alternate clients while still supporting fully typed Trpc context.
|
- 'Lift' auth context into server middleware to support authenticated api (rest) endpoints for alternate clients while still supporting fully typed Trpc context.
|
||||||
|
|
||||||
## Version 1.1.0
|
## Version 1.1.0
|
||||||
|
|
||||||
- Upgrade Prisma to version 5 to improve performance (https://www.prisma.io/docs/guides/upgrade-guides/upgrading-versions/upgrading-to-prisma-5)
|
- Upgrade Prisma to version 5 to improve performance (https://www.prisma.io/docs/guides/upgrade-guides/upgrading-versions/upgrading-to-prisma-5)
|
||||||
|
|
||||||
```
|
```
|
||||||
npm install @prisma/client@5
|
npm install @prisma/client@5
|
||||||
npm install -D prisma@5
|
npm install -D prisma@5
|
||||||
@@ -21,17 +32,21 @@ npx prisma generate
|
|||||||
```
|
```
|
||||||
|
|
||||||
- Upgrade Nuxt to 3.7.0
|
- Upgrade Nuxt to 3.7.0
|
||||||
|
|
||||||
```
|
```
|
||||||
npx nuxi upgrade --force
|
npx nuxi upgrade --force
|
||||||
```
|
```
|
||||||
|
|
||||||
## Version 1.0.0
|
## Version 1.0.0
|
||||||
First Release version. If your package.json does not have a version attribute, this is the version you have.
|
|
||||||
|
First Release version. If your package.json does not have a version attribute, this is the version you have.
|
||||||
|
|
||||||
## Project Creation (for interest only)
|
## Project Creation (for interest only)
|
||||||
This is what I did to create the project including all the extra fiddly stuff. Putting this here so I don't forget.
|
|
||||||
|
This is what I did to create the project including all the extra fiddly stuff. Putting this here so I don't forget.
|
||||||
|
|
||||||
### Setup Nuxt
|
### Setup Nuxt
|
||||||
|
|
||||||
I Followed instructions from here https://nuxt.com/docs/getting-started/installation
|
I Followed instructions from here https://nuxt.com/docs/getting-started/installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -42,6 +57,7 @@ code nuxt3-boilerplate/
|
|||||||
npm install
|
npm install
|
||||||
npm run dev -- -o
|
npm run dev -- -o
|
||||||
```
|
```
|
||||||
|
|
||||||
### Setup Supabase
|
### Setup Supabase
|
||||||
|
|
||||||
To setup supabase and middleware, loosely follow instructions from https://www.youtube.com/watch?v=IcaL1RfnU44
|
To setup supabase and middleware, loosely follow instructions from https://www.youtube.com/watch?v=IcaL1RfnU44
|
||||||
@@ -53,18 +69,22 @@ npm install @nuxtjs/supabase
|
|||||||
```
|
```
|
||||||
|
|
||||||
add this to nuxt.config.ts
|
add this to nuxt.config.ts
|
||||||
|
|
||||||
```
|
```
|
||||||
modules: ['@nuxtjs/supabase']
|
modules: ['@nuxtjs/supabase']
|
||||||
```
|
```
|
||||||
|
|
||||||
### Setup Google OAuth
|
### Setup Google OAuth
|
||||||
|
|
||||||
Follow these instructions to add google oath https://supabase.com/docs/guides/auth/social-login/auth-google
|
Follow these instructions to add google oath https://supabase.com/docs/guides/auth/social-login/auth-google
|
||||||
|
|
||||||
### Nuxt-Supabase
|
### Nuxt-Supabase
|
||||||
Then I frigged around trying to get the nuxt-supabase module to work properly for the oauth flow. It's a bit of a mess TBH. Eventually I looked at the demo https://github.com/nuxt-modules/supabase/tree/main/demo like a chump and got it working
|
|
||||||
|
Then I frigged around trying to get the nuxt-supabase module to work properly for the oauth flow. It's a bit of a mess TBH. Eventually I looked at the demo https://github.com/nuxt-modules/supabase/tree/main/demo like a chump and got it working
|
||||||
|
|
||||||
### Integrating Prisma
|
### Integrating Prisma
|
||||||
This felt like a difficult decision at first. the Subabase client has some pseudo sql Ormy sort of features already
|
|
||||||
|
This felt like a difficult decision at first. the Subabase client has some pseudo sql Ormy sort of features already
|
||||||
but Prisma has this awesome schema management support and autogeneration of a typed client works great and reduces errors.
|
but Prisma has this awesome schema management support and autogeneration of a typed client works great and reduces errors.
|
||||||
I already had a schema lying around based on this (https://blog.checklyhq.com/building-a-multi-tenant-saas-data-model/) that was nearly what I needed and it was nice to be able to re-use it.
|
I already had a schema lying around based on this (https://blog.checklyhq.com/building-a-multi-tenant-saas-data-model/) that was nearly what I needed and it was nice to be able to re-use it.
|
||||||
|
|
||||||
@@ -72,6 +92,7 @@ I already had a schema lying around based on this (https://blog.checklyhq.com/bu
|
|||||||
npm install prisma --save-dev
|
npm install prisma --save-dev
|
||||||
npx prisma init
|
npx prisma init
|
||||||
```
|
```
|
||||||
|
|
||||||
go to Supabase -> settings -> database -> connection string -> URI.. and copy the URI into the
|
go to Supabase -> settings -> database -> connection string -> URI.. and copy the URI into the
|
||||||
DATABASE_URL setting created with prisma init.
|
DATABASE_URL setting created with prisma init.
|
||||||
still in database, go to 'Database password' and reset/set it and copy the password into the [YOUR-PASSWORD] placeholder in the URI
|
still in database, go to 'Database password' and reset/set it and copy the password into the [YOUR-PASSWORD] placeholder in the URI
|
||||||
@@ -85,10 +106,12 @@ npx prisma generate
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Stripe Integration
|
### Stripe Integration
|
||||||
This was a royal pain in the butt. Got some tips from https://github.com/jurassicjs/nuxt3-fullstack-tutorial and https://www.youtube.com/watch?v=A24aKCQ-rf4&t=895s Official docs try to be helpful but succeed only in confusing things https://stripe.com/docs/billing/quickstart
|
|
||||||
|
|
||||||
I set up a Stripe account with a couple of 'Products' with a single price each to represent my different plans. These price id's are embedded into the Pricing page.
|
This was a royal pain in the butt. Got some tips from https://github.com/jurassicjs/nuxt3-fullstack-tutorial and https://www.youtube.com/watch?v=A24aKCQ-rf4&t=895s Official docs try to be helpful but succeed only in confusing things https://stripe.com/docs/billing/quickstart
|
||||||
|
|
||||||
|
I set up a Stripe account with a couple of 'Products' with a single price each to represent my different plans. These price id's are embedded into the Pricing page.
|
||||||
|
|
||||||
### Key things I learned
|
### Key things I learned
|
||||||
- You need to need to pre-emptively create a Stripe user *before* you send them to the checkout page so that you know who they are when the webhook comes back.
|
|
||||||
- There are like a Billion Fricking Webhooks you *can* subscribe to but for an MVP, you just need the *customer.subscription* events and you basically treat them all the same.
|
- You need to need to pre-emptively create a Stripe user _before_ you send them to the checkout page so that you know who they are when the webhook comes back.
|
||||||
|
- There are like a Billion Fricking Webhooks you _can_ subscribe to but for an MVP, you just need the _customer.subscription_ events and you basically treat them all the same.
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ Demo site [here](https://nuxt3-saas-boilerplate.netlify.app/)
|
|||||||
|
|
||||||
Pottery Helper [here](https://potteryhelper.com/)
|
Pottery Helper [here](https://potteryhelper.com/)
|
||||||
|
|
||||||
|
## Sister Project using React + Next 13
|
||||||
|
Sick of Vue.js/Nuxt3, why not checkout React/Next sister project [SupaNext SaaS](https://github.com/JavascriptMick/supanext-saas)
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
Discord [here](https://discord.gg/3hWPDTA4kD)
|
Discord [here](https://discord.gg/3hWPDTA4kD)
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
|
|
||||||
const supabase = useSupabaseAuthClient();
|
|
||||||
const user = useSupabaseUser();
|
const user = useSupabaseUser();
|
||||||
const accountStore = useAccountStore()
|
|
||||||
const { dbUser, activeAccountId } = storeToRefs(accountStore);
|
|
||||||
const notifyStore = useNotifyStore();
|
|
||||||
const { notifications } = storeToRefs(notifyStore);
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await accountStore.init()
|
|
||||||
});
|
|
||||||
|
|
||||||
async function signout() {
|
|
||||||
await supabase.auth.signOut();
|
|
||||||
if(accountStore){
|
|
||||||
accountStore.signout();
|
|
||||||
}
|
|
||||||
navigateTo('/', {replace: true});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="navbar bg-base-100">
|
<div class="navbar bg-base-100">
|
||||||
<div class="toast toast-end toast-top">
|
<Notifications/>
|
||||||
<div v-for="notification in notifications" :class="notification.type">
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
@click.prevent="notifyStore.removeNotification(notification)"
|
|
||||||
type="button"
|
|
||||||
class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700"
|
|
||||||
aria-label="Close">
|
|
||||||
<span class="sr-only">Close</span>
|
|
||||||
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
|
|
||||||
</button>
|
|
||||||
<span> {{notification.message}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="navbar-start">
|
<div class="navbar-start">
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<label tabindex="0" class="btn btn-ghost lg:hidden">
|
<label tabindex="0" class="btn btn-ghost lg:hidden">
|
||||||
@@ -60,27 +27,6 @@
|
|||||||
<li v-if="!user"><a title="github" href="https://github.com/JavascriptMick/supanuxt-saas"><Icon name="mdi:github"/></a></li>
|
<li v-if="!user"><a title="github" href="https://github.com/JavascriptMick/supanuxt-saas"><Icon name="mdi:github"/></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-end" v-if="user">
|
<UserAccount v-if="user" :user="user"/>
|
||||||
<div class="dropdown dropdown-end">
|
|
||||||
<label tabindex="0" class="btn btn-ghost btn-circle avatar">
|
|
||||||
<div class="w-10 rounded-full">
|
|
||||||
<img v-if="user.user_metadata.avatar_url" :src="user.user_metadata.avatar_url" alt="avatar image"/>
|
|
||||||
<img v-else src="~/assets/images/avatar.svg" alt="default avatar image"/>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<ul tabindex="0" class="mt-3 p-2 shadow menu menu-compact dropdown-content bg-base-100 rounded-box w-52">
|
|
||||||
<li v-if="user">{{ user.email }}</li>
|
|
||||||
<li><NuxtLink to="/account">Account</NuxtLink></li>
|
|
||||||
<li><a href="#" @click.prevent="signout()">Signout</a></li>
|
|
||||||
<template v-if="dbUser?.memberships && dbUser?.memberships.length > 1">
|
|
||||||
<li>Switch Account</li>
|
|
||||||
<li v-for="membership in dbUser?.memberships">
|
|
||||||
<a v-if="membership.account_id !== activeAccountId && !membership.pending" href="#" @click="accountStore.changeActiveAccount(membership.account_id)">{{ membership.account.name }}</a>
|
|
||||||
<span v-if="membership.pending">{{ membership.account.name }} (pending)</span>
|
|
||||||
</li>
|
|
||||||
</template>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
39
components/Notifications.client.vue
Normal file
39
components/Notifications.client.vue
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { NotificationType } from '#imports';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
|
const notifyStore = useNotifyStore();
|
||||||
|
const { notifications } = storeToRefs(notifyStore);
|
||||||
|
|
||||||
|
const classNameForType = (type: NotificationType) => {
|
||||||
|
switch (type) {
|
||||||
|
case NotificationType.Info:
|
||||||
|
return "alert alert-info";
|
||||||
|
case NotificationType.Success:
|
||||||
|
return "alert alert-success";
|
||||||
|
case NotificationType.Warning:
|
||||||
|
return "alert alert-warning";
|
||||||
|
case NotificationType.Error:
|
||||||
|
return "alert alert-error";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="toast toast-end toast-top">
|
||||||
|
<div v-for="notification in notifications" :class="classNameForType(notification.type)" >
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
@click.prevent="notifyStore.removeNotification(notification)"
|
||||||
|
type="button"
|
||||||
|
class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700"
|
||||||
|
aria-label="Close">
|
||||||
|
<span class="sr-only">Close</span>
|
||||||
|
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
|
||||||
|
</button>
|
||||||
|
<span> {{notification.message}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
28
components/UserAccount/UserAccount.vue
Normal file
28
components/UserAccount/UserAccount.vue
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps({
|
||||||
|
user: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const { user } = props;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="navbar-end">
|
||||||
|
<div class="dropdown dropdown-end">
|
||||||
|
<label tabindex="0" class="btn btn-ghost btn-circle avatar">
|
||||||
|
<div class="w-10 rounded-full">
|
||||||
|
<img v-if="user.user_metadata?.avatar_url" :src="user.user_metadata.avatar_url" alt="avatar image"/>
|
||||||
|
<img v-else src="~/assets/images/avatar.svg" alt="default avatar image"/>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<ul tabindex="0" class="mt-3 p-2 shadow menu menu-compact dropdown-content bg-base-100 rounded-box w-52">
|
||||||
|
<li v-if="user">{{ user.email }}</li>
|
||||||
|
<li><NuxtLink to="/account">Account</NuxtLink></li>
|
||||||
|
<li><UserAccountSignout/></li>
|
||||||
|
<UserAccountSwitch/>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
20
components/UserAccount/UserAccountSignout.client.vue
Normal file
20
components/UserAccount/UserAccountSignout.client.vue
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const supabase = useSupabaseAuthClient();
|
||||||
|
const accountStore = useAccountStore();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await accountStore.init()
|
||||||
|
});
|
||||||
|
|
||||||
|
async function signout() {
|
||||||
|
await supabase.auth.signOut();
|
||||||
|
if(accountStore){
|
||||||
|
accountStore.signout();
|
||||||
|
}
|
||||||
|
navigateTo('/', {replace: true});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<a href="#" @click.prevent="signout()">Signout</a>
|
||||||
|
</template>
|
||||||
21
components/UserAccount/UserAccountSwitch.client.vue
Normal file
21
components/UserAccount/UserAccountSwitch.client.vue
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
|
const accountStore = useAccountStore()
|
||||||
|
const { dbUser, activeAccountId } = storeToRefs(accountStore);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await accountStore.init()
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<template v-if="dbUser?.memberships && dbUser?.memberships.length > 1">
|
||||||
|
<li>Switch Account</li>
|
||||||
|
<li v-for="membership in dbUser?.memberships">
|
||||||
|
<a v-if="membership.account_id !== activeAccountId && !membership.pending" href="#" @click="accountStore.changeActiveAccount(membership.account_id)">{{ membership.account.name }}</a>
|
||||||
|
<span v-if="membership.pending">{{ membership.account.name }} (pending)</span>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "supanuxt-saas",
|
"name": "supanuxt-saas",
|
||||||
"version": "1.4.0",
|
"version": "1.4.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "supanuxt-saas",
|
"name": "supanuxt-saas",
|
||||||
"version": "1.4.0",
|
"version": "1.4.1",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "supanuxt-saas",
|
"name": "supanuxt-saas",
|
||||||
"version": "1.4.0",
|
"version": "1.4.1",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Michael Dausmann",
|
"name": "Michael Dausmann",
|
||||||
"email": "mdausmann@gmail.com",
|
"email": "mdausmann@gmail.com",
|
||||||
|
|||||||
@@ -175,4 +175,5 @@ const user = useSupabaseUser()
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div></template>
|
</div>
|
||||||
|
</template>
|
||||||
|
|||||||
@@ -36,18 +36,19 @@
|
|||||||
|
|
||||||
<h2>Security of your information</h2>
|
<h2>Security of your information</h2>
|
||||||
|
|
||||||
<p>We take reasonable measures to protect your personal information from unauthorized access, use, or disclosure.
|
<p>We take reasonable measures to protect your personal information from unauthorized access, use, or disclosure.
|
||||||
However, no data transmission over the internet or electronic storage is completely secure, so we cannot guarantee
|
However, no data transmission over the internet or electronic storage is completely secure, so we cannot guarantee
|
||||||
the absolute security of your information.</p>
|
the absolute security of your information.</p>
|
||||||
|
|
||||||
<h2>Changes to this privacy statement</h2>
|
<h2>Changes to this privacy statement</h2>
|
||||||
|
|
||||||
<p>We may update this privacy statement from time to time. Any changes will be posted on this page, so please check
|
<p>We may update this privacy statement from time to time. Any changes will be posted on this page, so please check
|
||||||
back periodically to review the most current version of the statement.</p>
|
back periodically to review the most current version of the statement.</p>
|
||||||
|
|
||||||
<h2>Contact us</h2>
|
<h2>Contact us</h2>
|
||||||
|
|
||||||
<p>If you have any questions or concerns about our privacy practices, please contact us at [insert contact
|
<p>If you have any questions or concerns about our privacy practices, please contact us at [insert contact
|
||||||
information].</p>
|
information].</p>
|
||||||
|
|
||||||
</div></template>
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createTRPCNuxtClient, httpBatchLink } from 'trpc-nuxt/client'
|
import { createTRPCNuxtClient, httpBatchLink } from "trpc-nuxt/client";
|
||||||
import type { AppRouter } from '~/server/api/trpc/[trpc]'
|
import type { AppRouter } from "~/server/api/trpc/[trpc]";
|
||||||
import superjson from 'superjson';
|
import superjson from "superjson";
|
||||||
|
|
||||||
export default defineNuxtPlugin(() => {
|
export default defineNuxtPlugin(() => {
|
||||||
/**
|
/**
|
||||||
@@ -10,15 +10,15 @@ export default defineNuxtPlugin(() => {
|
|||||||
const client = createTRPCNuxtClient<AppRouter>({
|
const client = createTRPCNuxtClient<AppRouter>({
|
||||||
links: [
|
links: [
|
||||||
httpBatchLink({
|
httpBatchLink({
|
||||||
url: '/api/trpc',
|
url: "/api/trpc",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
transformer: superjson,
|
transformer: superjson,
|
||||||
})
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
provide: {
|
provide: {
|
||||||
client,
|
client,
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ export interface Notification{
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum NotificationType{
|
export enum NotificationType{
|
||||||
Info = "alert alert-info",
|
Info,
|
||||||
Success = "alert alert-success",
|
Success,
|
||||||
Warning = "alert alert-warning",
|
Warning,
|
||||||
Error = "alert alert-error",
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
|||||||
Reference in New Issue
Block a user