create new example

This commit is contained in:
Carlos Stenzel committed 2021-05-24 09:22:26 -03:00
1 parent 181b53bce8
commit 214f2a07a0
24 files changed
+3154

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

@@ -0,0 +1,3 @@
# Update these with your Supabase details from your project settings > API
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
+35
View File
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/
.env
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# vercel
.vercel
+11
View File
@@ -0,0 +1,11 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"printWidth": 100,
"svelteSortOrder" : "styles-scripts-markup",
"svelteStrictMode": true,
"svelteBracketNewLine": true,
"svelteAllowShorthand": false
}
+36
View File
@@ -0,0 +1,36 @@
<img src="./.assets/Screen.png">
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
@@ -0,0 +1,12 @@
import { default as HeadContainer } from 'next/head'
const Head = () => {
return (
<HeadContainer>
<title>Supabase Example</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
</HeadContainer>
)
}
export default Head
@@ -0,0 +1,87 @@
import React from 'react'
import AuthUser from '../../hooks/authUser'
import { Disclosure } from '@headlessui/react'
import { MenuIcon, XIcon } from '@heroicons/react/outline'
import MenuLogado from './menuLogado'
import MenuNotLogado from './menuNotLogado'
import Navigation from './navigation'
import classNames from '../../utils/classsesNames'
export default function Header() {
return (
<Disclosure as="nav" className="bg-gray-800">
{({ open }) => (
<>
<div className="max-w-7xl mx-auto px-2 sm:px-6 lg:px-8">
<div className="relative flex items-center justify-between h-16">
<div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
{/* Mobile menu button*/}
<Disclosure.Button className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
<span className="sr-only">Open main menu</span>
{open ? (
<XIcon className="block h-6 w-6" aria-hidden="true" />
) : (
<MenuIcon className="block h-6 w-6" aria-hidden="true" />
)}
</Disclosure.Button>
</div>
<div className="flex-1 flex items-center justify-center sm:items-stretch sm:justify-start">
<div className="flex-shrink-0 flex items-center text-white">
<img
className="h-8 w-auto"
src="https://supabase.io/new/images/logo-dark.png"
alt="supabase"
/>
</div>
<div className="hidden sm:block sm:ml-6">
<div className="flex space-x-4">
{Navigation.map((item) => (
<a
key={item.name}
href={item.href}
className={classNames(
item.current
? 'bg-gray-900 text-white'
: 'text-gray-300 hover:bg-gray-700 hover:text-white',
'px-3 py-2 rounded-md text-sm font-medium'
)}
aria-current={item.current ? 'page' : undefined}
>
{item.name}
</a>
))}
</div>
</div>
</div>
<div className="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
{/** notificacoes */}
{AuthUser() ? <MenuLogado /> : <MenuNotLogado />}
</div>
</div>
</div>
<Disclosure.Panel className="sm:hidden">
<div className="px-2 pt-2 pb-3 space-y-1">
{Navigation.map((item) => (
<a
key={item.name}
href={item.href}
className={classNames(
item.current
? 'bg-gray-900 text-white'
: 'text-gray-300 hover:bg-gray-700 hover:text-white',
'block px-3 py-2 rounded-md text-base font-medium'
)}
aria-current={item.current ? 'page' : undefined}
>
{item.name}
</a>
))}
</div>
</Disclosure.Panel>
</>
)}
</Disclosure>
)
}
@@ -0,0 +1,70 @@
import { Fragment } from 'react'
import { Menu, Transition } from '@headlessui/react'
import { UserCircleIcon } from '@heroicons/react/outline'
import classNames from '../../utils/classsesNames'
import { SignOut } from '../../hooks/authUser'
const MenuLogado = () => (
<Menu as="div" className="ml-3 relative">
{({ open }) => (
<>
<div>
<Menu.Button className="bg-gray-800 flex text-sm rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white">
<span className="sr-only">Open user menu</span>
<UserCircleIcon className="h-8 w-8 text-white" />
</Menu.Button>
</div>
<Transition
show={open}
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
static
className="origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg py-1 bg-white ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<Menu.Item>
{({ active }) => (
<a
href="/profile"
className={classNames(
active ? 'bg-gray-100' : '',
'block px-4 py-2 text-sm text-gray-700'
)}
>
Your Profile
</a>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<a
href="/#"
className={classNames(
active ? 'bg-gray-100' : '',
'block px-4 py-2 text-sm text-gray-700'
)}
>
Settings
</a>
)}
</Menu.Item>
<Menu.Item>
<button onClick={() => SignOut()} className="block px-4 py-2 text-sm text-gray-700">
Sign out
</button>
</Menu.Item>
</Menu.Items>
</Transition>
</>
)}
</Menu>
)
export default MenuLogado
@@ -0,0 +1,11 @@
import React from 'react'
import Link from 'next/link'
const MenuNotLogado = () => (
<div className="flex space-x-4">
<Link href="/auth">
<a className="text-white hover:bg-gray-700 px-3 py-2 rounded-md text-sm font-medium">LOGIN</a>
</Link>
</div>
)
export default MenuNotLogado
@@ -0,0 +1,7 @@
const Navigation = [
{ name: 'Home', href: '/', current: true },
{ name: 'Jobs', href: '#', current: false },
{ name: 'Developers', href: '#', current: false },
]
export default Navigation
@@ -0,0 +1,71 @@
import { useEffect, useState, createContext, useContext } from 'react'
import { supabase } from '../utils/initSupabase'
import { useRouter } from 'next/router'
export const SignOut = async () => {
await supabase.auth.signOut()
}
export const RequireAuth = () => {
const { user } = useUser()
const router = useRouter()
useEffect(() => {
if (!user) {
router.push('/auth')
}
}, [user, router])
}
export const AuthRedirect = () => {
const { user } = useUser()
const router = useRouter()
useEffect(() => {
if (user) {
router.push('/profile')
}
}, [user, router])
}
export const UserContext = createContext()
export const UserContextProvider = (props) => {
const [session, setSession] = useState(false)
const [user, setUser] = useState(false)
useEffect(() => {
const session = supabase.auth.session()
setSession(session)
setUser(session?.user ?? false)
const { data: authListener } = supabase.auth.onAuthStateChange(async (event, session) => {
setSession(session)
setUser(session?.user ?? false)
})
return () => {
authListener.unsubscribe()
}
}, [])
const value = {
session,
user,
}
return <UserContext.Provider value={value} {...props} />
}
export const useUser = () => {
const context = useContext(UserContext)
if (context === undefined) {
throw new Error(`useUser must be used within a UserContextProvider.`)
}
return context
}
const AuthUser = () => {
const { user } = useUser()
return user
}
export default AuthUser
@@ -0,0 +1,27 @@
{
"name": "nextjs-auth-tailwind",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"format": "prettier --write './**/*.{js,jsx,ts,tsx,css,md,json}' --config ./.prettierrc"
},
"dependencies": {
"@headlessui/react": "^1.2.0",
"@heroicons/react": "^1.0.1",
"@supabase/supabase-js": "^1.11.15",
"@supabase/ui": "^0.26.1",
"@tailwindcss/typography": "^0.4.0",
"next": "10.2.2",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"autoprefixer": "^10.2.5",
"postcss": "^8.3.0",
"prettier": "^2.3.0",
"tailwindcss": "^2.1.2"
}
}
@@ -0,0 +1,15 @@
import React from 'react'
import { UserContextProvider } from '../hooks/authUser'
import 'tailwindcss/tailwind.css'
import '../styles/globals.css'
export default function MyApp({ Component, pageProps }) {
return (
<main className={'dark'}>
<UserContextProvider>
<Component {...pageProps} />
</UserContextProvider>
</main>
)
}
@@ -0,0 +1,36 @@
import React from 'react'
import { AuthRedirect } from '../hooks/authUser'
import { supabase } from '../utils/initSupabase'
import { Auth, Card, Typography, Space } from '@supabase/ui'
import Head from '../components/Head'
import Header from '../components/Header'
const AuthPage = () => {
AuthRedirect()
return (
<>
<Head />
<Header />
<div className="authcontainer">
<Card>
<Space direction="vertical" size={8}>
<div>
<Typography.Title level={3}>Welcome</Typography.Title>
</div>
<Auth
supabaseClient={supabase}
providers={['google', 'github']}
view={'sign_in'}
socialLayout="horizontal"
socialButtonSize="xlarge"
/>
</Space>
</Card>
</div>
</>
)
}
export default AuthPage
@@ -0,0 +1,44 @@
import Header from '../components/Header'
import Head from '../components/Head'
const Index = () => {
return (
<>
<Head />
<Header />
<main className="mt-10 mx-auto max-w-7xl px-4 sm:mt-12 sm:px-6 md:mt-16 lg:mt-20 lg:px-8 xl:mt-28">
<div className="sm:text-center lg:text-left">
<h1 className="text-4xl tracking-tight font-extrabold text-white sm:text-5xl md:text-6xl">
<span className="block xl:inline">The Open Source</span>{' '}
<span className="block text-green-400 xl:inline">Firebase Alternative</span>
</h1>
<p className="mt-3 text-base text-white sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0">
Create a backend in less than 2 minutes. Start your project with a Postgres Database,
Authentication, instant APIs, realtime subscriptions and Storage.
</p>
<div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-start">
<div className="rounded-md shadow">
<a
href="#"
className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-green-400 hover:bg-green-600 md:py-4 md:text-lg md:px-10"
>
Get started
</a>
</div>
<div className="mt-3 sm:mt-0 sm:ml-3">
<a
href="#"
className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-green-400 bg-indigo-100 hover:bg-indigo-200 md:py-4 md:text-lg md:px-10"
>
Live demo
</a>
</div>
</div>
</div>
</main>
</>
)
}
export default Index
@@ -0,0 +1,32 @@
import React from 'react'
import { useUser, RequireAuth } from '../hooks/authUser'
import { Card, Typography, Space } from '@supabase/ui'
import Header from '../components/Header'
export default function Profile() {
RequireAuth()
const { user } = useUser()
return (
<>
<Header />
{user && (
<div style={{ maxWidth: '620px', margin: '96px auto' }}>
<Card>
<Space direction="vertical" size={6}>
<Typography.Text>Youre signed in</Typography.Text>
<Typography.Text strong>Email: {user.email}</Typography.Text>
<Typography.Text type="success">User data:</Typography.Text>
<Typography.Text>
<pre>{JSON.stringify(user, null, 2)}</pre>
</Typography.Text>
</Space>
</Card>
</div>
)}
</>
)
}
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -0,0 +1,4 @@
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,29 @@
body {
background: #181818;
}
/*
* Auth
*/
.authcontainer {
max-width: 420px;
margin: 96px auto;
}
.authcontainer a {
color: #8b5cf6 !important;
}
.authcontainer button[type='submit'] {
background: #8b5cf6 !important;
}
.authcontainer input:focus {
border-color: #8b5cf6 !important;
}
.authcontainer .sbui-typography-text-danger {
top: 3px !important;
position: absolute !important;
}
@@ -0,0 +1,11 @@
module.exports = {
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [require('@tailwindcss/typography')],
}
@@ -0,0 +1,5 @@
function classNames(...classes) {
return classes.filter(Boolean).join(' ')
}
export default classNames
@@ -0,0 +1,6 @@
import { createClient } from '@supabase/supabase-js'
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
)
File diff suppressed because it is too large. Load diff