🎉 Initial Commit
This commit is contained in:
parent
7dba4810ef
commit
16aed743d9
4
application/.prettierrc
Normal file
4
application/.prettierrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 120,
|
||||||
|
"tabWidth": 2
|
||||||
|
}
|
12
application/app.vue
Normal file
12
application/app.vue
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<n-message-provider>
|
||||||
|
<nuxt-layout>
|
||||||
|
<nuxt-page />
|
||||||
|
</nuxt-layout>
|
||||||
|
</n-message-provider>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { NMessageProvider } from "naive-ui";
|
||||||
|
import "@/assets/css/index.css";
|
||||||
|
</script>
|
15
application/assets/css/index.css
Normal file
15
application/assets/css/index.css
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
@import "@ibm/plex/css/ibm-plex.css";
|
||||||
|
|
||||||
|
.font-mono {
|
||||||
|
font-family: "IBM Plex Mono", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-sans {
|
||||||
|
font-family: "IBM Plex Sans", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: "IBM Plex Sans", sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
BIN
application/bun.lockb
Executable file
BIN
application/bun.lockb
Executable file
Binary file not shown.
3
application/components/brand/header.vue
Normal file
3
application/components/brand/header.vue
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<div>Fuxi</div>
|
||||||
|
</template>
|
5
application/components/helpful-links.vue
Normal file
5
application/components/helpful-links.vue
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<nuxt-link to="/about">About</nuxt-link>
|
||||||
|
</div>
|
||||||
|
</template>
|
30
application/components/problems/list.vue
Normal file
30
application/components/problems/list.vue
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<n-card segmented content-style="padding: 0">
|
||||||
|
<template #header>
|
||||||
|
<div>Problems</div>
|
||||||
|
<div class="text-xs font-normal">每天进步一点点!</div>
|
||||||
|
</template>
|
||||||
|
<n-list clickable hoverable>
|
||||||
|
<n-list-item v-for="item in (problems as any[])" class="px-[24px]">
|
||||||
|
<n-thing :title="item?.title">
|
||||||
|
<template #description>
|
||||||
|
<div class="text-xs flex gap-2">
|
||||||
|
<n-tag size="tiny" class="case-capital">{{ item?.type }}</n-tag>
|
||||||
|
<div>Published at {{ new Date(item?.created_at).toLocaleString() }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</n-thing>
|
||||||
|
</n-list-item>
|
||||||
|
</n-list>
|
||||||
|
</n-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { NCard, NList, NListItem, NThing, NTag } from "naive-ui";
|
||||||
|
|
||||||
|
const client = useSupabaseClient();
|
||||||
|
|
||||||
|
const { data: problems } = await client.from("problems").select(`*`).limit(20);
|
||||||
|
</script>
|
23
application/layouts/default.vue
Normal file
23
application/layouts/default.vue
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<template>
|
||||||
|
<n-layout>
|
||||||
|
<n-layout-header class="py-[18.5px] px-[36px]" bordered>
|
||||||
|
<nuxt-link class="brand-header" to="/">
|
||||||
|
<brand-header />
|
||||||
|
</nuxt-link>
|
||||||
|
</n-layout-header>
|
||||||
|
<n-layout-content class="h-[calc(100vh-70px)]" content-style="padding: 24px">
|
||||||
|
<slot />
|
||||||
|
</n-layout-content>
|
||||||
|
</n-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { NLayout, NLayoutHeader, NLayoutContent } from "naive-ui";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.brand-header {
|
||||||
|
all: unset;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
24
application/nuxt.config.ts
Normal file
24
application/nuxt.config.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
devtools: { enabled: true },
|
||||||
|
modules: ["@unocss/nuxt", '@pinia/nuxt', '@nuxtjs/supabase'],
|
||||||
|
build: {
|
||||||
|
transpile:
|
||||||
|
process.env.NODE_ENV === 'production'
|
||||||
|
? [
|
||||||
|
'naive-ui',
|
||||||
|
'vueuc',
|
||||||
|
'@css-render/vue3-ssr',
|
||||||
|
'@juggle/resize-observer'
|
||||||
|
]
|
||||||
|
: ['@juggle/resize-observer']
|
||||||
|
},
|
||||||
|
vite: {
|
||||||
|
optimizeDeps: {
|
||||||
|
include:
|
||||||
|
process.env.NODE_ENV === 'development'
|
||||||
|
? ['naive-ui', 'vueuc', 'date-fns-tz/formatInTimeZone']
|
||||||
|
: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
@ -11,8 +11,18 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/devtools": "latest",
|
"@nuxt/devtools": "latest",
|
||||||
|
"@nuxtjs/supabase": "latest",
|
||||||
|
"@pinia/nuxt": "latest",
|
||||||
|
"@unocss/nuxt": "^0.58.0",
|
||||||
|
"@vicons/carbon": "^0.12.0",
|
||||||
|
"naive-ui": "^2.35.0",
|
||||||
"nuxt": "^3.8.2",
|
"nuxt": "^3.8.2",
|
||||||
|
"unocss": "^0.58.0",
|
||||||
"vue": "^3.3.10",
|
"vue": "^3.3.10",
|
||||||
"vue-router": "^4.2.5"
|
"vue-router": "^4.2.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@ibm/plex": "^6.3.0",
|
||||||
|
"@supabase/supabase-js": "^2.39.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
5
application/pages/index.vue
Normal file
5
application/pages/index.vue
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div class="md:max-w-[720px] mx-auto">
|
||||||
|
<problems-list />
|
||||||
|
</div>
|
||||||
|
</template>
|
60
application/pages/login.vue
Normal file
60
application/pages/login.vue
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<template>
|
||||||
|
<div class="h-full w-full flex flex-col gap-5 justify-center items-center">
|
||||||
|
<brand-header />
|
||||||
|
<n-card segmented class="w-[380px]">
|
||||||
|
<template #header>
|
||||||
|
<div class="text-center">Sign in</div>
|
||||||
|
<div class="text-center text-xs font-normal">With your email</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<n-form @submit.prevent="submit">
|
||||||
|
<n-form-item label="Email">
|
||||||
|
<n-input v-model:value="payload.email" placeholder="Your email" />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="Password">
|
||||||
|
<n-input v-model:value="payload.password" type="password" placeholder="Your password" />
|
||||||
|
</n-form-item>
|
||||||
|
<n-button :loading="loading" attr-type="submit" class="w-full" type="primary">Login</n-button>
|
||||||
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
<div class="flex w-[360px] justify-between">
|
||||||
|
<nuxt-link>Haven't an account?</nuxt-link>
|
||||||
|
<helpful-links />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { NCard, NForm, NFormItem, NInput, NButton } from "naive-ui";
|
||||||
|
import { useMessage } from "naive-ui";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
const client = useSupabaseClient();
|
||||||
|
const message = useMessage();
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const payload = ref({
|
||||||
|
email: "",
|
||||||
|
password: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
async function submit() {
|
||||||
|
if (!payload.value.email || !payload.value.password) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
const { error } = await client.auth.signInWithPassword({
|
||||||
|
email: payload.value.email,
|
||||||
|
password: payload.value.password,
|
||||||
|
});
|
||||||
|
if (error) throw error;
|
||||||
|
message.success("Welcome back!");
|
||||||
|
navigateTo("/");
|
||||||
|
} catch (err: any) {
|
||||||
|
message.error(err.error_description || err.message);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
31
application/plugins/naive-ui.ts
Normal file
31
application/plugins/naive-ui.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { setup } from '@css-render/vue3-ssr'
|
||||||
|
import { defineNuxtPlugin } from '#app'
|
||||||
|
|
||||||
|
export default defineNuxtPlugin((nuxtApp) => {
|
||||||
|
if (process.server) {
|
||||||
|
const { collect } = setup(nuxtApp.vueApp)
|
||||||
|
const originalRenderMeta = nuxtApp.ssrContext?.renderMeta
|
||||||
|
nuxtApp.ssrContext = nuxtApp.ssrContext || {}
|
||||||
|
nuxtApp.ssrContext.renderMeta = () => {
|
||||||
|
if (!originalRenderMeta) {
|
||||||
|
return {
|
||||||
|
headTags: collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const originalMeta = originalRenderMeta()
|
||||||
|
if ('then' in originalMeta) {
|
||||||
|
return originalMeta.then((resolvedOriginalMeta) => {
|
||||||
|
return {
|
||||||
|
...resolvedOriginalMeta,
|
||||||
|
headTags: resolvedOriginalMeta['headTags'] + collect()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...originalMeta,
|
||||||
|
headTags: originalMeta['headTags'] + collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
5
application/uno.config.ts
Normal file
5
application/uno.config.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { defineConfig, presetUno } from "unocss";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
presets: [presetUno({ preflight: false })],
|
||||||
|
});
|
@ -1,75 +0,0 @@
|
|||||||
# Nuxt 3 Minimal Starter
|
|
||||||
|
|
||||||
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
Make sure to install the dependencies:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# npm
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# pnpm
|
|
||||||
pnpm install
|
|
||||||
|
|
||||||
# yarn
|
|
||||||
yarn install
|
|
||||||
|
|
||||||
# bun
|
|
||||||
bun install
|
|
||||||
```
|
|
||||||
|
|
||||||
## Development Server
|
|
||||||
|
|
||||||
Start the development server on `http://localhost:3000`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# npm
|
|
||||||
npm run dev
|
|
||||||
|
|
||||||
# pnpm
|
|
||||||
pnpm run dev
|
|
||||||
|
|
||||||
# yarn
|
|
||||||
yarn dev
|
|
||||||
|
|
||||||
# bun
|
|
||||||
bun run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
## Production
|
|
||||||
|
|
||||||
Build the application for production:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# npm
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# pnpm
|
|
||||||
pnpm run build
|
|
||||||
|
|
||||||
# yarn
|
|
||||||
yarn build
|
|
||||||
|
|
||||||
# bun
|
|
||||||
bun run build
|
|
||||||
```
|
|
||||||
|
|
||||||
Locally preview production build:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# npm
|
|
||||||
npm run preview
|
|
||||||
|
|
||||||
# pnpm
|
|
||||||
pnpm run preview
|
|
||||||
|
|
||||||
# yarn
|
|
||||||
yarn preview
|
|
||||||
|
|
||||||
# bun
|
|
||||||
bun run preview
|
|
||||||
```
|
|
||||||
|
|
||||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
|
@ -1,5 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<NuxtWelcome />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
@ -1,4 +0,0 @@
|
|||||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
|
||||||
export default defineNuxtConfig({
|
|
||||||
devtools: { enabled: true }
|
|
||||||
})
|
|
5418
display/yarn.lock
5418
display/yarn.lock
File diff suppressed because it is too large
Load Diff
19
supabase/migrations/20231210071647_profiles.sql
Normal file
19
supabase/migrations/20231210071647_profiles.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
create table public.profiles (
|
||||||
|
id uuid not null references auth.users on delete cascade,
|
||||||
|
username varchar(64),
|
||||||
|
nickname varchar(256),
|
||||||
|
school_id int8,
|
||||||
|
|
||||||
|
primary key (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
alter table public.profiles enable row level security;
|
||||||
|
|
||||||
|
create policy "Public profiles are viewable by everyone." on profiles
|
||||||
|
for select using (true);
|
||||||
|
|
||||||
|
create policy "Users can insert their own profile." on profiles
|
||||||
|
for insert with check (auth.uid() = id);
|
||||||
|
|
||||||
|
create policy "Users can update own profile." on profiles
|
||||||
|
for update using (auth.uid() = id);
|
19
supabase/migrations/20231210071842_problems.sql
Normal file
19
supabase/migrations/20231210071842_problems.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
create table
|
||||||
|
public.problems (
|
||||||
|
id bigint generated by default as identity,
|
||||||
|
title text not null,
|
||||||
|
description text not null,
|
||||||
|
type character varying not null,
|
||||||
|
tags character varying[] null,
|
||||||
|
author uuid null,
|
||||||
|
is_draft boolean null default true,
|
||||||
|
is_hidden boolean null default false,
|
||||||
|
created_at timestamp with time zone null default now(),
|
||||||
|
constraint problems_pkey primary key (id),
|
||||||
|
constraint problems_author_fkey foreign key (author) references auth.users (id)
|
||||||
|
) tablespace pg_default;
|
||||||
|
|
||||||
|
alter table public.problems enable row level security;
|
||||||
|
|
||||||
|
create policy "Public problems are viewable by everyone." on problems
|
||||||
|
for select using (true);
|
Loading…
Reference in New Issue
Block a user