diff --git a/apps/survey-admin/index.html b/apps/survey-admin/index.html
index 23ff550..2b87072 100644
--- a/apps/survey-admin/index.html
+++ b/apps/survey-admin/index.html
@@ -7,7 +7,6 @@
-
-
설문 만들기
-
+
+
+
+
+
+ {surveySections.map((section, sectionIndex) => (
+
+
{`section ${sectionIndex + 1}`}
+ {section.items.map((item, itemIndex) => (
+
handleActiveItem(sectionIndex, itemIndex)}
+ onAddOptions={handleAddOption}
+ onChangeOptionText={handleChangeOptionText}
+ onChangeItemTitle={handleChangeItemTitle}
+ />
+ ))}
+
+ ))}
+
+
+
+
+
);
}
-
-export default App;
diff --git a/apps/survey-admin/src/app/components/SurveyItem/SurveyItem.css.ts b/apps/survey-admin/src/app/components/SurveyItem/SurveyItem.css.ts
new file mode 100644
index 0000000..2aa77e0
--- /dev/null
+++ b/apps/survey-admin/src/app/components/SurveyItem/SurveyItem.css.ts
@@ -0,0 +1,6 @@
+import { style } from '@vanilla-extract/css';
+
+export const cardWrapper = style({
+ padding: '24px',
+ paddingTop: '22px',
+});
diff --git a/apps/survey-admin/src/app/components/SurveyItem/SurveyItem.tsx b/apps/survey-admin/src/app/components/SurveyItem/SurveyItem.tsx
new file mode 100644
index 0000000..bfd9ff5
--- /dev/null
+++ b/apps/survey-admin/src/app/components/SurveyItem/SurveyItem.tsx
@@ -0,0 +1,75 @@
+import { Card, Radio } from '@ssoon-servey/shared-ui';
+import { cardWrapper } from './SurveyItem.css';
+import { type SurveyItem } from '../../hooks/query/useServey';
+
+interface SurveyItemProps {
+ item: SurveyItem;
+ onActiveItem: () => void;
+ onAddOptions: () => void;
+ onChangeOptionText: (value: string, optionIndex: number) => void;
+ onChangeItemTitle: (value: string) => void;
+}
+
+const SurveyItem = ({
+ item,
+ onActiveItem,
+ onAddOptions,
+ onChangeOptionText,
+ onChangeItemTitle,
+}: SurveyItemProps) => {
+ const handleAddOptions = () => {
+ onAddOptions();
+ };
+ const handleItemsTitleChange = (e: React.ChangeEvent
) => {
+ const { value } = e.currentTarget;
+ onChangeItemTitle(value);
+ };
+ const handleOptionTextChange = (
+ e: React.ChangeEvent,
+ optionIndex: number
+ ) => {
+ const { value } = e.currentTarget;
+ onChangeOptionText(value, optionIndex);
+ };
+ return (
+
+
+
+ );
+};
+
+export default SurveyItem;
diff --git a/apps/survey-admin/src/app/components/SurveyItem/index.ts b/apps/survey-admin/src/app/components/SurveyItem/index.ts
new file mode 100644
index 0000000..77597a1
--- /dev/null
+++ b/apps/survey-admin/src/app/components/SurveyItem/index.ts
@@ -0,0 +1 @@
+export { default } from './SurveyItem';
diff --git a/apps/survey-admin/src/app/components/ToolBar/Toolbar.css.ts b/apps/survey-admin/src/app/components/ToolBar/Toolbar.css.ts
new file mode 100644
index 0000000..dac9ac5
--- /dev/null
+++ b/apps/survey-admin/src/app/components/ToolBar/Toolbar.css.ts
@@ -0,0 +1,10 @@
+import { style } from '@vanilla-extract/css';
+
+export const cardWrapper = style({
+ padding: '8px',
+ display: 'flex',
+ flexDirection: 'column',
+ gap: '4px',
+ justifyContent: 'center',
+ alignItems: 'center',
+});
diff --git a/apps/survey-admin/src/app/components/ToolBar/Toolbar.tsx b/apps/survey-admin/src/app/components/ToolBar/Toolbar.tsx
new file mode 100644
index 0000000..cd55c34
--- /dev/null
+++ b/apps/survey-admin/src/app/components/ToolBar/Toolbar.tsx
@@ -0,0 +1,37 @@
+import { Card } from '@ssoon-servey/shared-ui';
+import { cardWrapper } from './Toolbar.css';
+
+interface Props {
+ onAddItems: () => void;
+ onAddSections: () => void;
+}
+
+const ToolBar = ({ onAddItems, onAddSections }: Props) => {
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default ToolBar;
diff --git a/apps/survey-admin/src/app/components/ToolBar/index.ts b/apps/survey-admin/src/app/components/ToolBar/index.ts
new file mode 100644
index 0000000..1c8b228
--- /dev/null
+++ b/apps/survey-admin/src/app/components/ToolBar/index.ts
@@ -0,0 +1 @@
+export { default } from './Toolbar';
diff --git a/apps/survey-admin/src/hooks/query/useServey.ts b/apps/survey-admin/src/app/hooks/query/useServey.ts
similarity index 88%
rename from apps/survey-admin/src/hooks/query/useServey.ts
rename to apps/survey-admin/src/app/hooks/query/useServey.ts
index fd1f12e..8cb7ad9 100644
--- a/apps/survey-admin/src/hooks/query/useServey.ts
+++ b/apps/survey-admin/src/app/hooks/query/useServey.ts
@@ -1,26 +1,26 @@
import { useSupabaseContext } from '@ssoon-servey/supabase';
-interface Option {
+export type Option = {
text: string;
-}
+};
-interface Item {
+export type SurveyItem = {
title: string;
type: 'radio' | 'select' | 'checkbox' | 'textarea';
required: boolean;
- options?: Option[];
-}
+ options: Option[];
+};
-interface Section {
+export type SurveySection = {
title?: string;
- items: Item[];
-}
+ items: SurveyItem[];
+};
-export interface Survey {
+export type Survey = {
title: string;
description?: string;
- sections: Section[];
-}
+ sections: SurveySection[];
+};
export const useCreateSurvey = () => {
const { supabase } = useSupabaseContext();
@@ -33,7 +33,10 @@ export const useCreateSurvey = () => {
return survey;
};
- const createSections = async (serveyId: number, sections: Section[]) => {
+ const createSections = async (
+ serveyId: number,
+ sections: SurveySection[]
+ ) => {
const { data: survey_section } = await supabase
.from('survey_sections')
.insert(
@@ -48,7 +51,7 @@ export const useCreateSurvey = () => {
const createSurveyItems = async (
sectionIds: number[],
- sections: Section[]
+ sections: SurveySection[]
) => {
const insertItems: {
section_id: number;
@@ -80,7 +83,7 @@ export const useCreateSurvey = () => {
const createItemOptions = async (
surveyItemIds: number[],
- sections: Section[]
+ sections: SurveySection[]
) => {
const insertOptions: { item_id: number; option_text: string }[] = [];
diff --git a/apps/survey-admin/src/app/hooks/viewmodel/useSurveyViewModel.ts b/apps/survey-admin/src/app/hooks/viewmodel/useSurveyViewModel.ts
new file mode 100644
index 0000000..40fac2f
--- /dev/null
+++ b/apps/survey-admin/src/app/hooks/viewmodel/useSurveyViewModel.ts
@@ -0,0 +1,139 @@
+import React from 'react';
+import {
+ type SurveySection,
+ type Survey,
+ useCreateSurvey,
+ type SurveyItem as Item,
+} from '../query/useServey';
+import { insertItem } from '@ssoon-servey/utils';
+import { useState } from 'react';
+import { produce } from 'immer';
+
+const newItem: Item = {
+ title: '',
+ type: 'radio',
+ required: false,
+ options: [{ text: '옵션1' }],
+};
+const newSection: SurveySection = {
+ title: undefined,
+ items: [newItem],
+};
+
+const useSurveyViewModel = () => {
+ const [survey, setSurvey] = useState>({
+ title: '',
+ description: '',
+ });
+ const [currentActiveItemIndex, setCurrentActiveItemIndex] = useState({
+ sectionId: 0,
+ itemId: 0,
+ });
+
+ const [surveySections, setSurveySections] = useState([
+ newSection,
+ ]);
+
+ const mutate = useCreateSurvey();
+
+ const handleSurveyInput = (e: React.ChangeEvent) => {
+ const { value, name } = e.currentTarget;
+ setSurvey((prev) => ({
+ ...prev,
+ [name]: value,
+ }));
+ };
+
+ const handleAddItems = () => {
+ const { sectionId, itemId } = currentActiveItemIndex;
+ const nextItemId = itemId + 1;
+
+ setSurveySections((sections) =>
+ produce(sections, (sections) => {
+ const section = sections[sectionId];
+ section.items = insertItem(section.items, nextItemId, newItem);
+ })
+ );
+
+ setCurrentActiveItemIndex((prev) => ({
+ ...prev,
+ itemId: nextItemId,
+ }));
+ };
+
+ const handleAddOption = () => {
+ const { sectionId, itemId } = currentActiveItemIndex;
+ setSurveySections((sections) =>
+ produce(sections, (sections) => {
+ const section = sections[sectionId];
+ const item = section.items[itemId];
+ item.options.push({
+ text: 'radio option 1번 째',
+ });
+ })
+ );
+ };
+
+ const handleAddSections = () => {
+ const { sectionId } = currentActiveItemIndex;
+ const nextSectionId = sectionId + 1;
+ setSurveySections((section) =>
+ insertItem(section, nextSectionId, newSection)
+ );
+ setCurrentActiveItemIndex((prev) => ({
+ ...prev,
+ sectionId: nextSectionId,
+ }));
+ };
+
+ const handleActiveItem = (sectionId: number, itemId: number) => {
+ setCurrentActiveItemIndex({ sectionId, itemId });
+ };
+
+ const handleChangeItemTitle = (value: string) => {
+ const { sectionId, itemId } = currentActiveItemIndex;
+
+ setSurveySections((sections) =>
+ produce(sections, (sections) => {
+ const section = sections[sectionId];
+ const item = section.items[itemId];
+ item.title = value;
+ })
+ );
+ };
+
+ const handleChangeOptionText = (value: string, optionIndex: number) => {
+ const { sectionId, itemId } = currentActiveItemIndex;
+
+ setSurveySections((sections) =>
+ produce(sections, (sections) => {
+ const section = sections[sectionId];
+ const item = section.items[itemId];
+ const option = item.options[optionIndex];
+ option.text = value;
+ })
+ );
+ };
+
+ const onSubmit = () => {
+ mutate({
+ title: survey.title,
+ description: survey.description,
+ sections: surveySections,
+ });
+ };
+ return {
+ survey,
+ handleSurveyInput,
+ surveySections,
+ handleActiveItem,
+ handleAddOption,
+ handleChangeOptionText,
+ handleChangeItemTitle,
+ handleAddItems,
+ handleAddSections,
+ onSubmit,
+ };
+};
+
+export default useSurveyViewModel;
diff --git a/apps/survey-admin/src/main.tsx b/apps/survey-admin/src/main.tsx
index f594e6b..03fb0ab 100644
--- a/apps/survey-admin/src/main.tsx
+++ b/apps/survey-admin/src/main.tsx
@@ -1,8 +1,8 @@
import { StrictMode } from 'react';
import * as ReactDOM from 'react-dom/client';
import { SupabaseProvider } from '@ssoon-servey/supabase';
-
import App from './app/app';
+import '@ssoon-servey/shared-ui/css';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
diff --git a/apps/survey-admin/src/styles.css b/apps/survey-admin/src/styles.css
deleted file mode 100644
index 90d4ee0..0000000
--- a/apps/survey-admin/src/styles.css
+++ /dev/null
@@ -1 +0,0 @@
-/* You can add global styles to this file, and also import other style files */
diff --git a/apps/survey-admin/tsconfig.app.json b/apps/survey-admin/tsconfig.app.json
index cd44a1e..d84be45 100644
--- a/apps/survey-admin/tsconfig.app.json
+++ b/apps/survey-admin/tsconfig.app.json
@@ -19,5 +19,5 @@
"src/**/*.spec.jsx",
"src/**/*.test.jsx"
],
- "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
+ "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx", "../../libs/shared/ui/src/global.css.ts"]
}
diff --git a/apps/survey-admin/vite.config.ts b/apps/survey-admin/vite.config.ts
index 80baebe..6fd857e 100644
--- a/apps/survey-admin/vite.config.ts
+++ b/apps/survey-admin/vite.config.ts
@@ -2,6 +2,7 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
+import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';
export default defineConfig({
root: __dirname,
@@ -17,7 +18,7 @@ export default defineConfig({
host: 'localhost',
},
- plugins: [react(), nxViteTsPaths()],
+ plugins: [react(), nxViteTsPaths(), vanillaExtractPlugin({})],
// Uncomment this if you are using workers.
// worker: {
diff --git a/libs/shared/ui/src/global.css.ts b/libs/shared/ui/src/global.css.ts
new file mode 100644
index 0000000..16aa346
--- /dev/null
+++ b/libs/shared/ui/src/global.css.ts
@@ -0,0 +1,45 @@
+import { globalStyle, createGlobalTheme } from '@vanilla-extract/css';
+
+export const vars = createGlobalTheme(':root', {
+ color: {
+ primary100: '#f0ebf8',
+ primary200: '#e9e7f7',
+ primary500: '#673ab7',
+ grayScale00: '#fff',
+ grayScale100: '#dadce0',
+ grayScale500: '#adb1ba',
+ grayScale900: '#202124',
+ red500: '#d93025',
+ },
+ font: {
+ body: 'Roboto, RobotoDraft, Helvetica, Arial, sans-serif',
+ },
+});
+
+globalStyle('*, *::before, *::after', {
+ boxSizing: 'border-box',
+});
+
+globalStyle('*', {
+ margin: 0,
+ padding: 0,
+ font: 'inherit',
+});
+
+globalStyle('button', {
+ cursor: 'pointer',
+ borderRadius: 0,
+ border: 'none',
+ backgroundColor: 'transparent',
+});
+
+globalStyle('html, body', {
+ margin: 0,
+ fontFamily: vars.font.body,
+ color: vars.color.grayScale900,
+ accentColor: vars.color.primary500,
+});
+
+globalStyle('body', {
+ backgroundColor: vars.color.primary100,
+});
diff --git a/libs/shared/ui/src/index.ts b/libs/shared/ui/src/index.ts
index cd654c7..bdbcb22 100644
--- a/libs/shared/ui/src/index.ts
+++ b/libs/shared/ui/src/index.ts
@@ -1 +1,4 @@
-export * from './lib/SharedUi';
+export * from './lib/Card';
+export * from './lib/Radio';
+export * from './lib/Checkbox';
+export * from './global.css';
diff --git a/libs/shared/ui/src/lib/Card/Card.css.ts b/libs/shared/ui/src/lib/Card/Card.css.ts
new file mode 100644
index 0000000..239b47a
--- /dev/null
+++ b/libs/shared/ui/src/lib/Card/Card.css.ts
@@ -0,0 +1,15 @@
+import { style } from '@vanilla-extract/css';
+import { vars } from '../../global.css';
+
+export const container = style({
+ margin: 'auto',
+ maxWidth: '90vw',
+ width: '640px',
+});
+
+export const card = style({
+ backgroundColor: vars.color.grayScale00,
+ border: `1px solid ${vars.color.grayScale100}`,
+ borderRadius: '8px',
+ position: 'relative',
+});
diff --git a/libs/shared/ui/src/lib/Card/Card.tsx b/libs/shared/ui/src/lib/Card/Card.tsx
new file mode 100644
index 0000000..1bfb191
--- /dev/null
+++ b/libs/shared/ui/src/lib/Card/Card.tsx
@@ -0,0 +1,15 @@
+import { card } from './Card.css';
+
+interface CardProps {
+ children: React.ReactNode;
+ onClick?: () => void;
+}
+const Card = ({ children, onClick }: CardProps) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export default Card;
diff --git a/libs/shared/ui/src/lib/Card/index.ts b/libs/shared/ui/src/lib/Card/index.ts
new file mode 100644
index 0000000..06c3388
--- /dev/null
+++ b/libs/shared/ui/src/lib/Card/index.ts
@@ -0,0 +1 @@
+export { default as Card } from './Card';
diff --git a/libs/shared/ui/src/lib/Checkbox/Checkbox.css.ts b/libs/shared/ui/src/lib/Checkbox/Checkbox.css.ts
new file mode 100644
index 0000000..fb260dc
--- /dev/null
+++ b/libs/shared/ui/src/lib/Checkbox/Checkbox.css.ts
@@ -0,0 +1,6 @@
+import { style } from '@vanilla-extract/css';
+
+export const checkbox = style({
+ width: '18px',
+ height: '18px',
+});
diff --git a/libs/shared/ui/src/lib/Checkbox/Checkbox.tsx b/libs/shared/ui/src/lib/Checkbox/Checkbox.tsx
new file mode 100644
index 0000000..bee7147
--- /dev/null
+++ b/libs/shared/ui/src/lib/Checkbox/Checkbox.tsx
@@ -0,0 +1,7 @@
+import { checkbox } from './Checkbox.css';
+
+const Checkbox = (props: React.InputHTMLAttributes) => {
+ return ;
+};
+
+export default Checkbox;
diff --git a/libs/shared/ui/src/lib/Checkbox/index.ts b/libs/shared/ui/src/lib/Checkbox/index.ts
new file mode 100644
index 0000000..8edbc50
--- /dev/null
+++ b/libs/shared/ui/src/lib/Checkbox/index.ts
@@ -0,0 +1 @@
+export { default as Checkbox } from './Checkbox';
diff --git a/libs/shared/ui/src/lib/Radio/Radio.css.ts b/libs/shared/ui/src/lib/Radio/Radio.css.ts
new file mode 100644
index 0000000..eea956b
--- /dev/null
+++ b/libs/shared/ui/src/lib/Radio/Radio.css.ts
@@ -0,0 +1,6 @@
+import { style } from '@vanilla-extract/css';
+
+export const radio = style({
+ width: '18px',
+ height: '18px',
+});
diff --git a/libs/shared/ui/src/lib/Radio/Radio.tsx b/libs/shared/ui/src/lib/Radio/Radio.tsx
new file mode 100644
index 0000000..27ffcb5
--- /dev/null
+++ b/libs/shared/ui/src/lib/Radio/Radio.tsx
@@ -0,0 +1,7 @@
+import { radio } from './Radio.css';
+
+const Radio = (props: React.InputHTMLAttributes) => {
+ return ;
+};
+
+export default Radio;
diff --git a/libs/shared/ui/src/lib/Radio/index.ts b/libs/shared/ui/src/lib/Radio/index.ts
new file mode 100644
index 0000000..fe25e2e
--- /dev/null
+++ b/libs/shared/ui/src/lib/Radio/index.ts
@@ -0,0 +1 @@
+export { default as Radio } from './Radio';
diff --git a/libs/shared/ui/src/lib/SharedUi.tsx b/libs/shared/ui/src/lib/SharedUi.tsx
deleted file mode 100644
index bd7ef9f..0000000
--- a/libs/shared/ui/src/lib/SharedUi.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import styles from './shared-ui.module.css';
-
-/* eslint-disable-next-line */
-export interface SharedUiProps {}
-
-export function SharedUi(props: SharedUiProps) {
- return (
-
-
Welcome to SharedUi!
-
- );
-}
-
-export default SharedUi;
diff --git a/libs/shared/ui/src/lib/shared-ui.module.css b/libs/shared/ui/src/lib/shared-ui.module.css
deleted file mode 100644
index 45c2aa4..0000000
--- a/libs/shared/ui/src/lib/shared-ui.module.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Replace this with your own classes
- *
- * e.g.
- * .container {
- * }
-*/
diff --git a/libs/utils/.eslintrc.json b/libs/utils/.eslintrc.json
new file mode 100644
index 0000000..adbe7ae
--- /dev/null
+++ b/libs/utils/.eslintrc.json
@@ -0,0 +1,25 @@
+{
+ "extends": ["../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.json"],
+ "parser": "jsonc-eslint-parser",
+ "rules": {
+ "@nx/dependency-checks": "error"
+ }
+ }
+ ]
+}
diff --git a/libs/utils/README.md b/libs/utils/README.md
new file mode 100644
index 0000000..b6583b1
--- /dev/null
+++ b/libs/utils/README.md
@@ -0,0 +1,7 @@
+# utils
+
+This library was generated with [Nx](https://nx.dev).
+
+## Building
+
+Run `nx build utils` to build the library.
diff --git a/libs/utils/package.json b/libs/utils/package.json
new file mode 100644
index 0000000..893abea
--- /dev/null
+++ b/libs/utils/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "@ssoon-servey/utils",
+ "version": "0.0.1",
+ "dependencies": {
+ "tslib": "^2.3.0"
+ },
+ "type": "commonjs",
+ "main": "./src/index.js",
+ "typings": "./src/index.d.ts"
+}
diff --git a/libs/utils/project.json b/libs/utils/project.json
new file mode 100644
index 0000000..69d3353
--- /dev/null
+++ b/libs/utils/project.json
@@ -0,0 +1,19 @@
+{
+ "name": "utils",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "libs/utils/src",
+ "projectType": "library",
+ "targets": {
+ "build": {
+ "executor": "@nx/js:tsc",
+ "outputs": ["{options.outputPath}"],
+ "options": {
+ "outputPath": "dist/libs/utils",
+ "main": "libs/utils/src/index.ts",
+ "tsConfig": "libs/utils/tsconfig.lib.json",
+ "assets": ["libs/utils/*.md"]
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/libs/utils/src/index.ts b/libs/utils/src/index.ts
new file mode 100644
index 0000000..3a4bf34
--- /dev/null
+++ b/libs/utils/src/index.ts
@@ -0,0 +1 @@
+export * from './lib/utils';
diff --git a/libs/utils/src/lib/utils.ts b/libs/utils/src/lib/utils.ts
new file mode 100644
index 0000000..da258af
--- /dev/null
+++ b/libs/utils/src/lib/utils.ts
@@ -0,0 +1,3 @@
+export const insertItem = (array: T[], index: number, newItem: T): T[] => {
+ return [...array.slice(0, index), newItem, ...array.slice(index)];
+};
diff --git a/libs/utils/tsconfig.json b/libs/utils/tsconfig.json
new file mode 100644
index 0000000..db7b566
--- /dev/null
+++ b/libs/utils/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "module": "commonjs",
+ "forceConsistentCasingInFileNames": true,
+ "strict": true,
+ "noImplicitOverride": true,
+ "noPropertyAccessFromIndexSignature": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.lib.json"
+ }
+ ]
+}
diff --git a/libs/utils/tsconfig.lib.json b/libs/utils/tsconfig.lib.json
new file mode 100644
index 0000000..faa09cc
--- /dev/null
+++ b/libs/utils/tsconfig.lib.json
@@ -0,0 +1,10 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "declaration": true,
+ "types": ["node"]
+ },
+ "include": ["src/**/*.ts"],
+ "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"]
+}
diff --git a/nx.json b/nx.json
index 36d4ada..85960bb 100644
--- a/nx.json
+++ b/nx.json
@@ -53,6 +53,11 @@
"cache": true,
"dependsOn": ["^build"],
"inputs": ["production", "^production"]
+ },
+ "@nx/js:tsc": {
+ "cache": true,
+ "dependsOn": ["^build"],
+ "inputs": ["production", "^production"]
}
}
}
diff --git a/package.json b/package.json
index 37abdf0..b892912 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,8 @@
"private": true,
"dependencies": {
"@supabase/supabase-js": "^2.39.7",
+ "@vanilla-extract/css": "^1.14.1",
+ "immer": "^10.0.3",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-router-dom": "6.11.2"
@@ -33,6 +35,7 @@
"@types/react-dom": "18.2.14",
"@typescript-eslint/eslint-plugin": "^6.13.2",
"@typescript-eslint/parser": "^6.13.2",
+ "@vanilla-extract/vite-plugin": "^4.0.4",
"@vitejs/plugin-react": "^4.2.0",
"@vitest/coverage-v8": "^1.0.4",
"@vitest/ui": "^1.3.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 43a1f6a..891031d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,6 +8,12 @@ dependencies:
'@supabase/supabase-js':
specifier: ^2.39.7
version: 2.39.7
+ '@vanilla-extract/css':
+ specifier: ^1.14.1
+ version: 1.14.1
+ immer:
+ specifier: ^10.0.3
+ version: 10.0.3
react:
specifier: 18.2.0
version: 18.2.0
@@ -76,6 +82,9 @@ devDependencies:
'@typescript-eslint/parser':
specifier: ^6.13.2
version: 6.21.0(eslint@8.48.0)(typescript@5.3.3)
+ '@vanilla-extract/vite-plugin':
+ specifier: ^4.0.4
+ version: 4.0.4(@types/node@18.16.9)(vite@5.0.12)
'@vitejs/plugin-react':
specifier: ^4.2.0
version: 4.2.1(vite@5.0.12)
@@ -1446,7 +1455,6 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
regenerator-runtime: 0.14.1
- dev: true
/@babel/template@7.24.0:
resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==}
@@ -1495,6 +1503,9 @@ packages:
'@jridgewell/trace-mapping': 0.3.9
dev: true
+ /@emotion/hash@0.9.1:
+ resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==}
+
/@esbuild/aix-ppc64@0.19.12:
resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==}
engines: {node: '>=12'}
@@ -3294,6 +3305,77 @@ packages:
eslint-visitor-keys: 3.4.3
dev: true
+ /@vanilla-extract/babel-plugin-debug-ids@1.0.5:
+ resolution: {integrity: sha512-Rc9A6ylsw7EBErmpgqCMvc/Z/eEZxI5k1xfLQHw7f5HHh3oc5YfzsAsYU/PdmSNjF1dp3sGEViBdDltvwnfVaA==}
+ dependencies:
+ '@babel/core': 7.24.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@vanilla-extract/css@1.14.1:
+ resolution: {integrity: sha512-V4JUuHNjZgl64NGfkDJePqizkNgiSpphODtZEs4cCPuxLAzwOUJYATGpejwimJr1n529kq4DEKWexW22LMBokw==}
+ dependencies:
+ '@emotion/hash': 0.9.1
+ '@vanilla-extract/private': 1.0.3
+ chalk: 4.1.2
+ css-what: 6.1.0
+ cssesc: 3.0.0
+ csstype: 3.1.3
+ deep-object-diff: 1.1.9
+ deepmerge: 4.3.1
+ media-query-parser: 2.0.2
+ modern-ahocorasick: 1.0.1
+ outdent: 0.8.0
+
+ /@vanilla-extract/integration@7.1.1(@types/node@18.16.9):
+ resolution: {integrity: sha512-2JjDKL2HDTazis4oTkUFsQFUyw61k8oym9r0NOLSJC0JB0W25W1ryVZvDx74d3deIyB5AWbCselyzl3gja30kQ==}
+ dependencies:
+ '@babel/core': 7.24.0
+ '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.24.0)
+ '@vanilla-extract/babel-plugin-debug-ids': 1.0.5
+ '@vanilla-extract/css': 1.14.1
+ esbuild: 0.19.12
+ eval: 0.1.8
+ find-up: 5.0.0
+ javascript-stringify: 2.1.0
+ lodash: 4.17.21
+ mlly: 1.6.1
+ outdent: 0.8.0
+ vite: 5.0.12(@types/node@18.16.9)
+ vite-node: 1.3.1(@types/node@18.16.9)
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ dev: true
+
+ /@vanilla-extract/private@1.0.3:
+ resolution: {integrity: sha512-17kVyLq3ePTKOkveHxXuIJZtGYs+cSoev7BlP+Lf4916qfDhk/HBjvlYDe8egrea7LNPHKwSZJK/bzZC+Q6AwQ==}
+
+ /@vanilla-extract/vite-plugin@4.0.4(@types/node@18.16.9)(vite@5.0.12):
+ resolution: {integrity: sha512-cfg4GK274xzwbVFh8YWvQXNnsCMemvMMwej7V93TTBP2O8qzyTgsx5VJuiAPov3oUU8JWGboaTs16Vnoe5bZ9w==}
+ peerDependencies:
+ vite: ^4.0.3 || ^5.0.0
+ dependencies:
+ '@vanilla-extract/integration': 7.1.1(@types/node@18.16.9)
+ vite: 5.0.12(@types/node@18.16.9)
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ dev: true
+
/@vitejs/plugin-react@4.2.1(vite@5.0.12):
resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==}
engines: {node: ^14.18.0 || >=16.0.0}
@@ -3489,7 +3571,6 @@ packages:
engines: {node: '>=8'}
dependencies:
color-convert: 2.0.1
- dev: true
/ansi-styles@5.2.0:
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
@@ -3905,7 +3986,6 @@ packages:
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
- dev: true
/check-error@1.0.3:
resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==}
@@ -3975,7 +4055,6 @@ packages:
engines: {node: '>=7.0.0'}
dependencies:
color-name: 1.1.4
- dev: true
/color-name@1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
@@ -3983,7 +4062,6 @@ packages:
/color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
- dev: true
/colorette@2.0.20:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
@@ -4128,7 +4206,11 @@ packages:
/css-what@6.1.0:
resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
engines: {node: '>= 6'}
- dev: true
+
+ /cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
/csso@5.0.5:
resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
@@ -4146,7 +4228,6 @@ packages:
/csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
- dev: true
/damerau-levenshtein@1.0.8:
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
@@ -4235,10 +4316,12 @@ packages:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
dev: true
+ /deep-object-diff@1.1.9:
+ resolution: {integrity: sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==}
+
/deepmerge@4.3.1:
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
engines: {node: '>=0.10.0'}
- dev: true
/defaults@1.0.4:
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
@@ -4828,6 +4911,14 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /eval@0.1.8:
+ resolution: {integrity: sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==}
+ engines: {node: '>= 0.8'}
+ dependencies:
+ '@types/node': 18.16.9
+ require-like: 0.1.2
+ dev: true
+
/eventemitter3@4.0.7:
resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
dev: true
@@ -5307,7 +5398,6 @@ packages:
/has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
- dev: true
/has-property-descriptors@1.0.2:
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
@@ -5470,6 +5560,10 @@ packages:
engines: {node: '>= 4'}
dev: true
+ /immer@10.0.3:
+ resolution: {integrity: sha512-pwupu3eWfouuaowscykeckFmVTpqbzW+rXFCX8rQLkZzM9ftBmU/++Ra+o+L27mz03zJTlyV4UUr+fdKNffo4A==}
+ dev: false
+
/import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'}
@@ -5768,6 +5862,10 @@ packages:
minimatch: 3.1.2
dev: true
+ /javascript-stringify@2.1.0:
+ resolution: {integrity: sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==}
+ dev: true
+
/jest-diff@29.7.0:
resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -6103,6 +6201,11 @@ packages:
resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
dev: true
+ /media-query-parser@2.0.2:
+ resolution: {integrity: sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==}
+ dependencies:
+ '@babel/runtime': 7.24.0
+
/merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
dev: true
@@ -6242,6 +6345,9 @@ packages:
ufo: 1.4.0
dev: true
+ /modern-ahocorasick@1.0.1:
+ resolution: {integrity: sha512-yoe+JbhTClckZ67b2itRtistFKf8yPYelHLc7e5xAwtNAXxM6wJTUx2C7QeVSJFDzKT7bCIFyBVybPMKvmB9AA==}
+
/mrmime@2.0.0:
resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
engines: {node: '>=10'}
@@ -6542,6 +6648,9 @@ packages:
arch: 2.2.0
dev: true
+ /outdent@0.8.0:
+ resolution: {integrity: sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==}
+
/p-cancelable@2.1.1:
resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==}
engines: {node: '>=8'}
@@ -6882,7 +6991,6 @@ packages:
/regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
- dev: true
/regenerator-transform@0.15.2:
resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==}
@@ -6924,6 +7032,10 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /require-like@0.1.2:
+ resolution: {integrity: sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==}
+ dev: true
+
/requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
dev: true
@@ -7423,7 +7535,6 @@ packages:
engines: {node: '>=8'}
dependencies:
has-flag: 4.0.0
- dev: true
/supports-color@8.1.1:
resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
diff --git a/tsconfig.base.json b/tsconfig.base.json
index 77b3fee..c10bca3 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -16,7 +16,9 @@
"baseUrl": ".",
"paths": {
"@ssoon-servey/shared-ui": ["./libs/shared/ui/src/index.ts"],
- "@ssoon-servey/supabase": ["libs/supabase/src/index.ts"]
+ "@ssoon-servey/shared-ui/css": ["./libs/shared/ui/src/global.css.ts"],
+ "@ssoon-servey/supabase": ["libs/supabase/src/index.ts"],
+ "@ssoon-servey/utils": ["libs/utils/src/index.ts"]
}
},
"exclude": ["node_modules", "tmp"]