diff --git a/ui/.editorconfig b/ui/.editorconfig
new file mode 100644
index 0000000..9d08a1a
--- /dev/null
+++ b/ui/.editorconfig
@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/ui/.eslintignore b/ui/.eslintignore
new file mode 100644
index 0000000..9f81cf8
--- /dev/null
+++ b/ui/.eslintignore
@@ -0,0 +1,7 @@
+/dist
+/src-capacitor
+/src-cordova
+/.quasar
+/node_modules
+.eslintrc.cjs
+/quasar.config.*.temporary.compiled*
diff --git a/ui/.eslintrc.cjs b/ui/.eslintrc.cjs
new file mode 100644
index 0000000..b3d242c
--- /dev/null
+++ b/ui/.eslintrc.cjs
@@ -0,0 +1,69 @@
+module.exports = {
+ // https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy
+ // This option interrupts the configuration hierarchy at this file
+ // Remove this if you have an higher level ESLint config file (it usually happens into a monorepos)
+ root: true,
+
+ parserOptions: {
+ ecmaVersion: 2022, // Allows for the parsing of modern ECMAScript features
+ },
+
+ env: {
+ node: true,
+ browser: true
+ },
+
+ // Rules order is important, please avoid shuffling them
+ extends: [
+ // Base ESLint recommended rules
+ // 'eslint:recommended',
+
+ // Uncomment any of the lines below to choose desired strictness,
+ // but leave only one uncommented!
+ // See https://eslint.vuejs.org/rules/#available-rules
+ 'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention)
+ // 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
+ // 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
+
+ // https://github.com/prettier/eslint-config-prettier#installation
+ // usage with Prettier, provided by 'eslint-config-prettier'.
+ 'prettier'
+ ],
+
+ plugins: [
+ // https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files
+ // required to lint *.vue files
+ 'vue',
+
+ // https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674
+ // Prettier has not been included as plugin to avoid performance impact
+ // add it as an extension for your IDE
+
+ ],
+
+ globals: {
+ ga: 'readonly', // Google Analytics
+ cordova: 'readonly',
+ __statics: 'readonly',
+ __QUASAR_SSR__: 'readonly',
+ __QUASAR_SSR_SERVER__: 'readonly',
+ __QUASAR_SSR_CLIENT__: 'readonly',
+ __QUASAR_SSR_PWA__: 'readonly',
+ process: 'readonly',
+ Capacitor: 'readonly',
+ chrome: 'readonly'
+ },
+
+ // add your custom rules here
+ rules: {
+
+ 'prefer-promise-reject-errors': 'off',
+
+ // allow debugger during development only
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
+
+ //
+ 'vue/multi-word-component-names': 'off',
+ 'vue/no-dupe-keys': 'off'
+ }
+}
diff --git a/ui/.gitignore b/ui/.gitignore
new file mode 100644
index 0000000..f1d913c
--- /dev/null
+++ b/ui/.gitignore
@@ -0,0 +1,33 @@
+.DS_Store
+.thumbs.db
+node_modules
+
+# Quasar core related directories
+.quasar
+/dist
+/quasar.config.*.temporary.compiled*
+
+# Cordova related directories and files
+/src-cordova/node_modules
+/src-cordova/platforms
+/src-cordova/plugins
+/src-cordova/www
+
+# Capacitor related directories and files
+/src-capacitor/www
+/src-capacitor/node_modules
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+
+# local .env files
+.env.local*
diff --git a/ui/.npmrc b/ui/.npmrc
new file mode 100644
index 0000000..eb19082
--- /dev/null
+++ b/ui/.npmrc
@@ -0,0 +1,5 @@
+# pnpm-related options
+shamefully-hoist=true
+strict-peer-dependencies=false
+# to get the latest compatible packages when creating the project https://github.com/pnpm/pnpm/issues/6463
+resolution-mode=highest
diff --git a/ui/.vscode/extensions.json b/ui/.vscode/extensions.json
new file mode 100644
index 0000000..fe38802
--- /dev/null
+++ b/ui/.vscode/extensions.json
@@ -0,0 +1,15 @@
+{
+ "recommendations": [
+ "dbaeumer.vscode-eslint",
+ "esbenp.prettier-vscode",
+ "editorconfig.editorconfig",
+ "vue.volar",
+ "wayou.vscode-todo-highlight"
+ ],
+ "unwantedRecommendations": [
+ "octref.vetur",
+ "hookyqr.beautify",
+ "dbaeumer.jshint",
+ "ms-vscode.vscode-typescript-tslint-plugin"
+ ]
+}
\ No newline at end of file
diff --git a/ui/.vscode/settings.json b/ui/.vscode/settings.json
new file mode 100644
index 0000000..b3bb1e4
--- /dev/null
+++ b/ui/.vscode/settings.json
@@ -0,0 +1,15 @@
+{
+ "editor.bracketPairColorization.enabled": true,
+ "editor.guides.bracketPairs": true,
+ "editor.formatOnSave": true,
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "editor.codeActionsOnSave": [
+ "source.fixAll.eslint"
+ ],
+ "eslint.validate": [
+ "javascript",
+ "javascriptreact",
+ "typescript",
+ "vue"
+ ]
+}
\ No newline at end of file
diff --git a/ui/README.md b/ui/README.md
new file mode 100644
index 0000000..f39cece
--- /dev/null
+++ b/ui/README.md
@@ -0,0 +1,41 @@
+# Bordro Eşleme (tr.com.notitek.bordro-esleme)
+
+Bordro Eşleme
+
+## Install the dependencies
+```bash
+yarn
+# or
+npm install
+```
+
+### Start the app in development mode (hot-code reloading, error reporting, etc.)
+```bash
+quasar dev
+```
+
+
+### Lint the files
+```bash
+yarn lint
+# or
+npm run lint
+```
+
+
+### Format the files
+```bash
+yarn format
+# or
+npm run format
+```
+
+
+
+### Build the app for production
+```bash
+quasar build
+```
+
+### Customize the configuration
+See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-vite/quasar-config-js).
diff --git a/ui/index.html b/ui/index.html
new file mode 100644
index 0000000..3c8c78f
--- /dev/null
+++ b/ui/index.html
@@ -0,0 +1,21 @@
+
+
+
+ <%= productName %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/jsconfig.json b/ui/jsconfig.json
new file mode 100644
index 0000000..456944a
--- /dev/null
+++ b/ui/jsconfig.json
@@ -0,0 +1,39 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "src/*": [
+ "src/*"
+ ],
+ "app/*": [
+ "*"
+ ],
+ "components/*": [
+ "src/components/*"
+ ],
+ "layouts/*": [
+ "src/layouts/*"
+ ],
+ "pages/*": [
+ "src/pages/*"
+ ],
+ "assets/*": [
+ "src/assets/*"
+ ],
+ "boot/*": [
+ "src/boot/*"
+ ],
+ "stores/*": [
+ "src/stores/*"
+ ],
+ "vue$": [
+ "node_modules/vue/dist/vue.runtime.esm-bundler.js"
+ ]
+ }
+ },
+ "exclude": [
+ "dist",
+ ".quasar",
+ "node_modules"
+ ]
+}
\ No newline at end of file
diff --git a/ui/package.json b/ui/package.json
new file mode 100644
index 0000000..f3b1094
--- /dev/null
+++ b/ui/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "tr.com.notitek.bordro-esleme",
+ "version": "0.0.1",
+ "description": "Bordro Eşleme",
+ "productName": "Bordro Eşleme",
+ "author": "dev@notitek.com.tr",
+ "private": true,
+ "scripts": {
+ "lint": "eslint --ext .js,.vue ./",
+ "format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
+ "test": "echo \"No test specified\" && exit 0",
+ "dev": "quasar dev",
+ "build": "quasar build"
+ },
+ "dependencies": {
+ "@quasar/extras": "^1.16.4",
+ "axios": "^1.2.1",
+ "jwt-decode": "^4.0.0",
+ "pinia": "^2.0.11",
+ "quasar": "^2.8.0",
+ "vue": "^3.4.18",
+ "vue-router": "^4.0.12"
+ },
+ "devDependencies": {
+ "@quasar/app-vite": "^1.8.0",
+ "autoprefixer": "^10.4.2",
+ "eslint": "^8.11.0",
+ "eslint-config-prettier": "^8.1.0",
+ "eslint-plugin-vue": "^9.0.0",
+ "postcss": "^8.4.14",
+ "prettier": "^2.5.1",
+ "vite-plugin-checker": "^0.6.4"
+ },
+ "engines": {
+ "node": "^20 || ^18 || ^16",
+ "npm": ">= 6.13.4",
+ "yarn": ">= 1.21.1"
+ }
+}
diff --git a/ui/postcss.config.cjs b/ui/postcss.config.cjs
new file mode 100644
index 0000000..94b7b1c
--- /dev/null
+++ b/ui/postcss.config.cjs
@@ -0,0 +1,27 @@
+/* eslint-disable */
+// https://github.com/michael-ciniawsky/postcss-load-config
+
+module.exports = {
+ plugins: [
+ // https://github.com/postcss/autoprefixer
+ require('autoprefixer')({
+ overrideBrowserslist: [
+ 'last 4 Chrome versions',
+ 'last 4 Firefox versions',
+ 'last 4 Edge versions',
+ 'last 4 Safari versions',
+ 'last 4 Android versions',
+ 'last 4 ChromeAndroid versions',
+ 'last 4 FirefoxAndroid versions',
+ 'last 4 iOS versions'
+ ]
+ })
+
+ // https://github.com/elchininet/postcss-rtlcss
+ // If you want to support RTL css, then
+ // 1. yarn/npm install postcss-rtlcss
+ // 2. optionally set quasar.config.js > framework > lang to an RTL language
+ // 3. uncomment the following line:
+ // require('postcss-rtlcss')
+ ]
+}
diff --git a/ui/public/bres.png b/ui/public/bres.png
new file mode 100644
index 0000000..d198839
Binary files /dev/null and b/ui/public/bres.png differ
diff --git a/ui/public/favicon.ico b/ui/public/favicon.ico
new file mode 100644
index 0000000..324249b
Binary files /dev/null and b/ui/public/favicon.ico differ
diff --git a/ui/public/icons/favicon-128x128.png b/ui/public/icons/favicon-128x128.png
new file mode 100644
index 0000000..cd0ff81
Binary files /dev/null and b/ui/public/icons/favicon-128x128.png differ
diff --git a/ui/public/icons/favicon-16x16.png b/ui/public/icons/favicon-16x16.png
new file mode 100644
index 0000000..287e7fe
Binary files /dev/null and b/ui/public/icons/favicon-16x16.png differ
diff --git a/ui/public/icons/favicon-32x32.png b/ui/public/icons/favicon-32x32.png
new file mode 100644
index 0000000..dc7b85d
Binary files /dev/null and b/ui/public/icons/favicon-32x32.png differ
diff --git a/ui/public/icons/favicon-96x96.png b/ui/public/icons/favicon-96x96.png
new file mode 100644
index 0000000..9e8cfca
Binary files /dev/null and b/ui/public/icons/favicon-96x96.png differ
diff --git a/ui/public/notitek.png b/ui/public/notitek.png
new file mode 100644
index 0000000..1f6be05
Binary files /dev/null and b/ui/public/notitek.png differ
diff --git a/ui/quasar.config.js b/ui/quasar.config.js
new file mode 100644
index 0000000..8a11ef6
--- /dev/null
+++ b/ui/quasar.config.js
@@ -0,0 +1,240 @@
+/* eslint-env node */
+
+/*
+ * This file runs in a Node context (it's NOT transpiled by Babel), so use only
+ * the ES6 features that are supported by your Node version. https://node.green/
+ */
+
+// Configuration for your app
+// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js
+
+
+const { configure } = require('quasar/wrappers');
+
+
+module.exports = configure(function (ctx) {
+ return {
+ // https://v2.quasar.dev/quasar-cli-vite/prefetch-feature
+ // preFetch: true,
+
+ // app boot file (/src/boot)
+ // --> boot files are part of "main.js"
+ // https://v2.quasar.dev/quasar-cli-vite/boot-files
+ boot: [
+ 'axios',
+ 'version',
+ 'pinia',
+ ],
+
+ // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
+ css: [
+ 'app.scss'
+ ],
+
+ // https://github.com/quasarframework/quasar/tree/dev/extras
+ extras: [
+ // 'ionicons-v4',
+ 'mdi-v7',
+ // 'fontawesome-v6',
+ // 'eva-icons',
+ // 'themify',
+ // 'line-awesome',
+ 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both!
+
+ //'roboto-font', // optional, you are not bound to it
+ 'material-icons', // optional, you are not bound to it
+ ],
+
+ // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build
+ build: {
+ target: {
+ browser: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
+ node: 'node20'
+ },
+
+ vueRouterMode: 'history', // available values: 'hash', 'history'
+ // vueRouterBase,
+ // vueDevtools,
+ // vueOptionsAPI: false,
+
+ // rebuildCache: true, // rebuilds Vite/linter/etc cache on startup
+
+ // publicPath: '/',
+ // analyze: true,
+ env: {
+ apiAddr: (() => {
+ if (process.env.CUSTOM_API) {
+ return process.env.CUSTOM_API
+ } else {
+ if (ctx.dev) {
+ return 'http://localhost:41000/api'
+ } else {
+ return '/api'
+ }
+ }
+ })(),
+ wsAddr: (() => {
+ if (process.env.CUSTOM_WS) {
+ return process.env.CUSTOM_WS
+ } else {
+ if (ctx.dev) {
+ return 'ws://127.0.0.1:41000/ws'
+ } else {
+ return 'wss://bres.notitek.com.tr/ws'
+ }
+ }
+ })(),
+ },
+ // rawDefine: {}
+ // ignorePublicFolder: true,
+ // minify: false,
+ // polyfillModulePreload: true,
+ // distDir
+
+ extendViteConf (viteConf) {
+ viteConf.resolve.preserveSymlinks = true
+ },
+
+ // viteVuePluginOptions: {},
+
+ vitePlugins: [
+ ['vite-plugin-checker', {
+ eslint: {
+ lintCommand: 'eslint "./**/*.{js,mjs,cjs,vue}"'
+ }
+ }, { server: false }]
+ ]
+ },
+
+ // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer
+ devServer: {
+ // https: true
+ port:9400,
+ open: true // opens browser window automatically
+ },
+
+ // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework
+ framework: {
+ config: {},
+
+ // iconSet: 'material-icons', // Quasar icon set
+ // lang: 'en-US', // Quasar language pack
+
+ // For special cases outside of where the auto-import strategy can have an impact
+ // (like functional components as one of the examples),
+ // you can manually specify Quasar components/directives to be available everywhere:
+ //
+ // components: [],
+ // directives: [],
+
+ // Quasar plugins
+ plugins: [
+ 'Notify',
+ 'Loading',
+ 'Dialog',
+ 'Meta'
+ ]
+ },
+
+ // animations: 'all', // --- includes all animations
+ // https://v2.quasar.dev/options/animations
+ animations: [],
+
+ // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#property-sourcefiles
+ // sourceFiles: {
+ // rootComponent: 'src/App.vue',
+ // router: 'src/router/index',
+ // store: 'src/store/index',
+ // registerServiceWorker: 'src-pwa/register-service-worker',
+ // serviceWorker: 'src-pwa/custom-service-worker',
+ // pwaManifestFile: 'src-pwa/manifest.json',
+ // electronMain: 'src-electron/electron-main',
+ // electronPreload: 'src-electron/electron-preload'
+ // },
+
+ // https://v2.quasar.dev/quasar-cli-vite/developing-ssr/configuring-ssr
+ ssr: {
+ // ssrPwaHtmlFilename: 'offline.html', // do NOT use index.html as name!
+ // will mess up SSR
+
+ // extendSSRWebserverConf (esbuildConf) {},
+ // extendPackageJson (json) {},
+
+ pwa: false,
+
+ // manualStoreHydration: true,
+ // manualPostHydrationTrigger: true,
+
+ prodPort: 3000, // The default port that the production server should use
+ // (gets superseded if process.env.PORT is specified at runtime)
+
+ middlewares: [
+ 'render' // keep this as last one
+ ]
+ },
+
+ // https://v2.quasar.dev/quasar-cli-vite/developing-pwa/configuring-pwa
+ pwa: {
+ workboxMode: 'generateSW', // or 'injectManifest'
+ injectPwaMetaTags: true,
+ swFilename: 'sw.js',
+ manifestFilename: 'manifest.json',
+ useCredentialsForManifestTag: false,
+ // useFilenameHashes: true,
+ // extendGenerateSWOptions (cfg) {}
+ // extendInjectManifestOptions (cfg) {},
+ // extendManifestJson (json) {}
+ // extendPWACustomSWConf (esbuildConf) {}
+ },
+
+ // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-cordova-apps/configuring-cordova
+ cordova: {
+ // noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing
+ },
+
+ // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-capacitor-apps/configuring-capacitor
+ capacitor: {
+ hideSplashscreen: true
+ },
+
+ // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-electron-apps/configuring-electron
+ electron: {
+ // extendElectronMainConf (esbuildConf)
+ // extendElectronPreloadConf (esbuildConf)
+
+ // specify the debugging port to use for the Electron app when running in development mode
+ inspectPort: 5858,
+
+ bundler: 'packager', // 'packager' or 'builder'
+
+ packager: {
+ // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options
+
+ // OS X / Mac App Store
+ // appBundleId: '',
+ // appCategoryType: '',
+ // osxSign: '',
+ // protocol: 'myapp://path',
+
+ // Windows only
+ // win32metadata: { ... }
+ },
+
+ builder: {
+ // https://www.electron.build/configuration/configuration
+
+ appId: 'tr.com.notitek.bres'
+ }
+ },
+
+ // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-browser-extensions/configuring-bex
+ bex: {
+ contentScripts: [
+ 'my-content-script'
+ ],
+
+ // extendBexScriptsConf (esbuildConf) {}
+ // extendBexManifestJson (json) {}
+ }
+ }
+});
diff --git a/ui/src/App.vue b/ui/src/App.vue
new file mode 100644
index 0000000..79d5cce
--- /dev/null
+++ b/ui/src/App.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/ui/src/assets/quasar-logo-vertical.svg b/ui/src/assets/quasar-logo-vertical.svg
new file mode 100644
index 0000000..8210831
--- /dev/null
+++ b/ui/src/assets/quasar-logo-vertical.svg
@@ -0,0 +1,15 @@
+
\ No newline at end of file
diff --git a/ui/src/boot/.gitkeep b/ui/src/boot/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ui/src/boot/axios.js b/ui/src/boot/axios.js
new file mode 100644
index 0000000..9dbc942
--- /dev/null
+++ b/ui/src/boot/axios.js
@@ -0,0 +1,24 @@
+import { boot } from 'quasar/wrappers'
+import axios from 'axios'
+
+// Be careful when using SSR for cross-request state pollution
+// due to creating a Singleton instance here;
+// If any client changes this (global) instance, it might be a
+// good idea to move this instance creation inside of the
+// "export default () => {}" function below (which runs individually
+// for each client)
+const api = axios.create({ baseURL: 'https://api.example.com' })
+
+export default boot(({ app }) => {
+ // for use inside Vue files (Options API) through this.$axios and this.$api
+
+ app.config.globalProperties.$axios = axios
+ // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)
+ // so you won't necessarily have to import axios in each vue file
+
+ app.config.globalProperties.$api = api
+ // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
+ // so you can easily perform requests against your app's API
+})
+
+export { api }
diff --git a/ui/src/boot/pinia.js b/ui/src/boot/pinia.js
new file mode 100644
index 0000000..0f05547
--- /dev/null
+++ b/ui/src/boot/pinia.js
@@ -0,0 +1,4 @@
+import { useLoginStore } from 'stores/login'
+
+const store = useLoginStore()
+store.load()
diff --git a/ui/src/boot/version.js b/ui/src/boot/version.js
new file mode 100644
index 0000000..247117a
--- /dev/null
+++ b/ui/src/boot/version.js
@@ -0,0 +1,5 @@
+import vdata from '../../version'
+
+const $VERSION = vdata
+export { $VERSION }
+
diff --git a/ui/src/components/EssentialLink.vue b/ui/src/components/EssentialLink.vue
new file mode 100644
index 0000000..3a29f8f
--- /dev/null
+++ b/ui/src/components/EssentialLink.vue
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+ {{ props.title }}
+ {{ props.caption }}
+
+
+
+
+
diff --git a/ui/src/css/app.scss b/ui/src/css/app.scss
new file mode 100644
index 0000000..3038c18
--- /dev/null
+++ b/ui/src/css/app.scss
@@ -0,0 +1,12 @@
+// app global css in SCSS form
+@import "panel";
+
+@import url('https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;1,200;1,300;1,400;1,500;1,600;1,700&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Merriweather:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400;1,700;1,900&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400;1,700;1,900&display=swap');
+
+body {
+ font-family: 'Nunito', sans-serif;
+ font-size: 16px;
+ color: #334155;
+}
diff --git a/ui/src/css/panel.scss b/ui/src/css/panel.scss
new file mode 100644
index 0000000..01a8491
--- /dev/null
+++ b/ui/src/css/panel.scss
@@ -0,0 +1,44 @@
+:root {
+ --pcolor1: #c84b41;
+ --pcolor2: #020f40;
+ --pcolor3: #64748b;
+}
+
+.text-pcolor1 {
+ color: var(--pcolor1) !important;
+}
+
+.bg-pcolor1 {
+ background-color: var(--pcolor1) !important;
+}
+
+.text-pcolor2 {
+ color: var(--pcolor2) !important;
+}
+
+.bg-pcolor2 {
+ background-color: var(--pcolor2) !important;
+}
+
+.text-pcolor3 {
+ color: var(--pcolor3) !important;
+}
+
+.bg-pcolor3 {
+ background-color: var(--pcolor3) !important;
+}
+
+
+.border-bottom {
+ border-bottom: #cccccc 1px solid;
+}
+
+
+a.pcolor1link {
+ color: var(--pcolor1);
+ text-decoration: none;
+ &:hover {
+ color: var(--pcolor1);
+ text-decoration: underline;
+ }
+}
diff --git a/ui/src/css/quasar.variables.scss b/ui/src/css/quasar.variables.scss
new file mode 100644
index 0000000..3996ce1
--- /dev/null
+++ b/ui/src/css/quasar.variables.scss
@@ -0,0 +1,25 @@
+// Quasar SCSS (& Sass) Variables
+// --------------------------------------------------
+// To customize the look and feel of this app, you can override
+// the Sass/SCSS variables found in Quasar's source Sass/SCSS files.
+
+// Check documentation for full list of Quasar variables
+
+// Your own variables (that are declared here) and Quasar's own
+// ones will be available out of the box in your .vue/.scss/.sass files
+
+// It's highly recommended to change the default colors
+// to match your app's branding.
+// Tip: Use the "Theme Builder" on Quasar's documentation website.
+
+$primary : #1976D2;
+$secondary : #26A69A;
+$accent : #9C27B0;
+
+$dark : #1D1D1D;
+$dark-page : #121212;
+
+$positive : #21BA45;
+$negative : #C10015;
+$info : #31CCEC;
+$warning : #F2C037;
diff --git a/ui/src/layouts/MainLayout.vue b/ui/src/layouts/MainLayout.vue
new file mode 100644
index 0000000..e4a792e
--- /dev/null
+++ b/ui/src/layouts/MainLayout.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+ Quasar App
+
+
+ Quasar v{{ $q.version }}
+
+
+
+
+
+
+ Essential Links
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/layouts/landingLayout.vue b/ui/src/layouts/landingLayout.vue
new file mode 100644
index 0000000..7f9dd8b
--- /dev/null
+++ b/ui/src/layouts/landingLayout.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+ Bordro Eşleştirme
+
+
+
+
+
+
+
+
+
+
+
+
+ Notitek
+
+
+
+
+ {{ $VERSION.version }}
+
+ {{ $VERSION.build }}
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/layouts/panelLayout.vue b/ui/src/layouts/panelLayout.vue
new file mode 100644
index 0000000..eba898c
--- /dev/null
+++ b/ui/src/layouts/panelLayout.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ v.flag }} {{ v.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/pages/ErrorNotFound.vue b/ui/src/pages/ErrorNotFound.vue
new file mode 100644
index 0000000..23041c4
--- /dev/null
+++ b/ui/src/pages/ErrorNotFound.vue
@@ -0,0 +1,29 @@
+
+
+
+
+ 404
+
+
+
+ Oops. Nothing here...
+
+
+
+
+
+
+
+
diff --git a/ui/src/pages/IndexPage.vue b/ui/src/pages/IndexPage.vue
new file mode 100644
index 0000000..a595c2d
--- /dev/null
+++ b/ui/src/pages/IndexPage.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/ui/src/pages/login.vue b/ui/src/pages/login.vue
new file mode 100644
index 0000000..7f314a0
--- /dev/null
+++ b/ui/src/pages/login.vue
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
diff --git a/ui/src/router/index.js b/ui/src/router/index.js
new file mode 100644
index 0000000..e28c96f
--- /dev/null
+++ b/ui/src/router/index.js
@@ -0,0 +1,66 @@
+import {
+ createMemoryHistory,
+ createRouter,
+ createWebHashHistory,
+ createWebHistory,
+} from 'vue-router'
+import routes from './routes'
+import useLoginStore from 'stores/login'
+
+/*
+ * If not building with SSR mode, you can
+ * directly export the Router instantiation;
+ *
+ * The function below can be async too; either use
+ * async/await or return a Promise which resolves
+ * with the Router instance.
+ */
+
+const createHistory = process.env.SERVER
+ ? createMemoryHistory
+ : (process.env.VUE_ROUTER_MODE === 'history'
+ ? createWebHistory
+ : createWebHashHistory)
+
+const Router = createRouter({
+ scrollBehavior: () => ({ left: 0, top: 0 }),
+ routes,
+
+ // Leave this as is and make changes in quasar.conf.js instead!
+ // quasar.conf.js -> build -> vueRouterMode
+ // quasar.conf.js -> build -> publicPath
+ history: createHistory(process.env.VUE_ROUTER_BASE),
+})
+
+Router.beforeEach(
+ (to, from) => {
+ const loginStore = useLoginStore()
+
+ const isLoggedIn = loginStore.IsLoggedIn()
+
+ // instead of having to check every route record with
+ // to.matched.some(record => record.meta.requiresAuth)
+
+ if (to.meta.requiresAuth && !isLoggedIn &&
+ ((to.path !== '/') || (to.path !== 'login'))) {
+ // this route requires auth, check if logged in
+ // if not, redirect to login page.
+
+ return {
+ path: '/login',
+ // save the location we were at to come back later
+ //query: { redirect: to.fullPath },
+ }
+ }
+
+ if ((isLoggedIn) && ((to.path === '/') || (to.path === 'login'))) {
+ return {
+ path: '/panel',
+ query: '',
+ }
+ }
+ },
+)
+
+export default Router
+
diff --git a/ui/src/router/routes.js b/ui/src/router/routes.js
new file mode 100644
index 0000000..695c004
--- /dev/null
+++ b/ui/src/router/routes.js
@@ -0,0 +1,33 @@
+
+const routes = [
+ {
+ path: '/',
+ component: () => import('layouts/panelLayout.vue'),
+ meta: {
+ requiresAuth: true
+ },
+ children: [
+ { path: '', component: () => import('pages/IndexPage.vue') },
+ ]
+ },
+
+ {
+ path: '/login',
+ component: () => import('layouts/landingLayout.vue'),
+ children: [
+ { path: '', component: () => import('pages/login.vue') }
+ ],
+ meta: {
+ requiresAuth: false
+ },
+ },
+
+ // Always leave this as last one,
+ // but you can also remove it
+ {
+ path: '/:catchAll(.*)*',
+ component: () => import('pages/ErrorNotFound.vue')
+ }
+]
+
+export default routes
diff --git a/ui/src/stores/index.js b/ui/src/stores/index.js
new file mode 100644
index 0000000..ca5bee5
--- /dev/null
+++ b/ui/src/stores/index.js
@@ -0,0 +1,20 @@
+import { store } from 'quasar/wrappers'
+import { createPinia } from 'pinia'
+
+/*
+ * If not building with SSR mode, you can
+ * directly export the Store instantiation;
+ *
+ * The function below can be async too; either use
+ * async/await or return a Promise which resolves
+ * with the Store instance.
+ */
+
+export default store((/* { ssrContext } */) => {
+ const pinia = createPinia()
+
+ // You can add Pinia plugins here
+ // pinia.use(SomePiniaPlugin)
+
+ return pinia
+})
diff --git a/ui/src/stores/login.js b/ui/src/stores/login.js
new file mode 100644
index 0000000..69f7954
--- /dev/null
+++ b/ui/src/stores/login.js
@@ -0,0 +1,79 @@
+import { defineStore } from 'pinia'
+import { LocalStorage } from 'quasar'
+import { api } from 'boot/axios'
+import { jwtDecode } from "jwt-decode"
+import Router from 'src/router/index'
+
+export const sessionName = 'bresSession'
+
+const defaultState = {
+ LoggedIn: false,
+ Token: '',
+ UsrKSUID: '',
+ ClientKSUID: '',
+ Email: '',
+ Fullname: '',
+}
+
+export const useLoginStore = defineStore('login', {
+ state: () => {
+ return JSON.parse(JSON.stringify(defaultState))
+ },
+ getters: {},
+ actions: {
+
+ login (payload) {
+ // kaldıysa önceki session'ı uçuralım
+ LocalStorage.remove(sessionName)
+ const ds = JSON.parse(JSON.stringify(defaultState))
+ Object.assign(this, ds)
+
+ payload['LoggedIn'] = true
+ const pl = JSON.parse(JSON.stringify(payload))
+ Object.assign(this, pl)
+ api.defaults.headers.common['Authorization'] = `Bearer ${payload.Token}`
+ LocalStorage.set(sessionName, payload)
+ },
+
+ logout () {
+ // todo: burada güvenlik zafiyeti var ! backend'de token invalidate edilmeli
+ // bunun için memlist'e ek bir claim tutulabilir
+ // ve jwtAuth verify koduna yazılıabilinir.
+ // örnek : https://dev.to/stevensunflash/a-working-solution-to-jwt-creation-and-invalidation-in-golang-4oe4
+ const ds = JSON.parse(JSON.stringify(defaultState))
+ Object.assign(this, ds)
+
+ api.defaults.headers.common['Authorization'] = ''
+ LocalStorage.remove(sessionName)
+
+ if (Router) {
+ Router.push('/login')
+ //router.push({ path: '/login', replace: true })
+ }
+ },
+
+ updateState (payload) {
+ Object.assign(this, payload)
+ api.defaults.headers.common['Authorization'] = `Bearer ${payload.Token}`
+ },
+
+ load() {
+ const authInfo = LocalStorage.getItem(sessionName)
+ if (authInfo) {
+ const decoded = jwtDecode(authInfo.Token)
+ const now = Date.now() / 1000
+ if (decoded.exp < now) {
+ this.logout()
+ } else {
+ this.updateState(authInfo)
+ }
+ }
+ },
+
+ IsLoggedIn () {
+ return this.LoggedIn
+ }
+ }
+})
+
+export default useLoginStore
diff --git a/ui/src/stores/store-flag.d.ts b/ui/src/stores/store-flag.d.ts
new file mode 100644
index 0000000..7677175
--- /dev/null
+++ b/ui/src/stores/store-flag.d.ts
@@ -0,0 +1,10 @@
+/* eslint-disable */
+// THIS FEATURE-FLAG FILE IS AUTOGENERATED,
+// REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
+import "quasar/dist/types/feature-flag";
+
+declare module "quasar/dist/types/feature-flag" {
+ interface QuasarFeatureFlags {
+ store: true;
+ }
+}