feat: added clien on vue.js and ionic
This commit is contained in:
25
client/package-lock.json
generated
25
client/package-lock.json
generated
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "client",
|
"name": "kawai-focus",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "client",
|
"name": "kawai-focus",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@capacitor/app": "8.0.0",
|
"@capacitor/app": "8.0.0",
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
"@capacitor/status-bar": "8.0.0",
|
"@capacitor/status-bar": "8.0.0",
|
||||||
"@ionic/vue": "^8.0.0",
|
"@ionic/vue": "^8.0.0",
|
||||||
"@ionic/vue-router": "^8.0.0",
|
"@ionic/vue-router": "^8.0.0",
|
||||||
|
"@tauri-apps/api": "^2.9.1",
|
||||||
|
"@tauri-apps/plugin-sql": "^2.3.1",
|
||||||
"ionicons": "^7.0.0",
|
"ionicons": "^7.0.0",
|
||||||
"vue": "^3.3.0",
|
"vue": "^3.3.0",
|
||||||
"vue-router": "^4.2.0"
|
"vue-router": "^4.2.0"
|
||||||
@@ -3143,6 +3145,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tauri-apps/api": {
|
||||||
|
"version": "2.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.9.1.tgz",
|
||||||
|
"integrity": "sha512-IGlhP6EivjXHepbBic618GOmiWe4URJiIeZFlB7x3czM0yDHHYviH1Xvoiv4FefdkQtn6v7TuwWCRfOGdnVUGw==",
|
||||||
|
"license": "Apache-2.0 OR MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/tauri"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tauri-apps/plugin-sql": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-sql/-/plugin-sql-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-iNgHnFIR+jRkx9INKVKepzMlxXtNkJUaWuhagFjT4dOttPaNyRnVHgwTjpqZhyVjiklDh2UdEPAJkQKiCPAekw==",
|
||||||
|
"license": "MIT OR Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@tauri-apps/api": "^2.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tootallnate/once": {
|
"node_modules/@tootallnate/once": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vue-tsc && vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"test:e2e": "cypress run",
|
"test:e2e": "cypress run",
|
||||||
"test:unit": "vitest",
|
"test:unit": "vitest",
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
"@capacitor/status-bar": "8.0.0",
|
"@capacitor/status-bar": "8.0.0",
|
||||||
"@ionic/vue": "^8.0.0",
|
"@ionic/vue": "^8.0.0",
|
||||||
"@ionic/vue-router": "^8.0.0",
|
"@ionic/vue-router": "^8.0.0",
|
||||||
|
"@tauri-apps/api": "^2.9.1",
|
||||||
|
"@tauri-apps/plugin-sql": "^2.3.1",
|
||||||
"ionicons": "^7.0.0",
|
"ionicons": "^7.0.0",
|
||||||
"vue": "^3.3.0",
|
"vue": "^3.3.0",
|
||||||
"vue-router": "^4.2.0"
|
"vue-router": "^4.2.0"
|
||||||
|
|||||||
@@ -4,14 +4,6 @@
|
|||||||
</ion-app>
|
</ion-app>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import { IonApp, IonRouterOutlet } from '@ionic/vue';
|
import { IonApp, IonRouterOutlet } from '@ionic/vue'
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'App',
|
|
||||||
components: {
|
|
||||||
IonApp,
|
|
||||||
IonRouterOutlet
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
8
client/src/config.js
Normal file
8
client/src/config.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { appLocalDataDir } from '@tauri-apps/api/path';
|
||||||
|
|
||||||
|
export async function getDB_URL() {
|
||||||
|
// Функция верёнт путь до бд
|
||||||
|
|
||||||
|
const appDir = await appLocalDataDir();
|
||||||
|
return `sqlite:${appDir}/timer.db`;
|
||||||
|
}
|
||||||
10
client/src/db/crud/timerCrud.js
Normal file
10
client/src/db/crud/timerCrud.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { getDb } from "../initDb";
|
||||||
|
import { SELECT_TIMERS } from "../dml/timerDML";
|
||||||
|
|
||||||
|
|
||||||
|
export async function getTimers() {
|
||||||
|
// Функция для получения списка таймеров
|
||||||
|
|
||||||
|
const db = await getDb();
|
||||||
|
return await db.select(SELECT_TIMERS);
|
||||||
|
}
|
||||||
11
client/src/db/ddl/timerDDL.js
Normal file
11
client/src/db/ddl/timerDDL.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export const CREATE_TIMER = `
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
CREATE TABLE IF NOT EXISTS timer (
|
||||||
|
title VARCHAR(200) NOT NULL,
|
||||||
|
pomodoro_time INTEGER NOT NULL,
|
||||||
|
break_time INTEGER NOT NULL,
|
||||||
|
break_long_time INTEGER NOT NULL,
|
||||||
|
count_pomodoro INTEGER NOT NULL,
|
||||||
|
id INTEGER NOT NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);`
|
||||||
6
client/src/db/dml/timerDML.js
Normal file
6
client/src/db/dml/timerDML.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export const SELECT_TIMERS = 'SELECT id, title, pomodoro_time, count_pomodoro FROM timer ORDER BY id DESC'
|
||||||
|
export const COUNT_TIMERS = 'SELECT COUNT(*) as cnt FROM timer'
|
||||||
|
export const INSERT_SEED_DB = `
|
||||||
|
INSERT INTO timer (title, pomodoro_time, break_time, break_long_time, count_pomodoro) VALUES
|
||||||
|
('Timer mini example', 10, 3, 15, 2), ('Timer max example', 90, 10, 40, 8)
|
||||||
|
`
|
||||||
26
client/src/db/initDb.js
Normal file
26
client/src/db/initDb.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import Database from '@tauri-apps/plugin-sql';
|
||||||
|
import { CREATE_TIMER } from './ddl/timerDDL';
|
||||||
|
import { getDB_URL } from '../config';
|
||||||
|
import { seedDb } from './seed';
|
||||||
|
|
||||||
|
let dbPromise = null;
|
||||||
|
|
||||||
|
export async function getDb() {
|
||||||
|
// Функция для получения подключения к базе данных
|
||||||
|
|
||||||
|
if (!dbPromise) {
|
||||||
|
dbPromise = (async () => {
|
||||||
|
try {
|
||||||
|
const dbUrl = await getDB_URL();
|
||||||
|
const db = await Database.load(dbUrl);
|
||||||
|
await db.execute(CREATE_TIMER);
|
||||||
|
await seedDb(db);
|
||||||
|
return db;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка инициализации базы данных', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
return await dbPromise; // await для консистентности
|
||||||
|
}
|
||||||
11
client/src/db/seed.js
Normal file
11
client/src/db/seed.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { INSERT_SEED_DB, COUNT_TIMERS } from './dml/timerDML'
|
||||||
|
|
||||||
|
|
||||||
|
export async function seedDb(db) {
|
||||||
|
// Функция для заполнения бд данными
|
||||||
|
|
||||||
|
const count = await db.select(COUNT_TIMERS);
|
||||||
|
if (count[0].cnt === 0) {
|
||||||
|
await db.execute(INSERT_SEED_DB);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,14 +8,53 @@ import {
|
|||||||
trashOutline
|
trashOutline
|
||||||
} from 'ionicons/icons';
|
} from 'ionicons/icons';
|
||||||
|
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { getTimers } from '../../db/crud/timerCrud';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TimersList',
|
name: 'TimersList',
|
||||||
components: {
|
components: {
|
||||||
IonIcon,
|
IonIcon,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
// Возвращаем иконки, чтобы они были доступны в шаблоне
|
const timers = ref([]);
|
||||||
|
const loading = ref(true);
|
||||||
|
const error = ref(null);
|
||||||
|
const expandedId = ref(null);
|
||||||
|
|
||||||
|
const loadTimers = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
error.value = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await getTimers();
|
||||||
|
timers.value = result;
|
||||||
|
} catch (err) {
|
||||||
|
error.value = err.message || 'Ошибка загрузки таймеров';
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleExpand = (id) => {
|
||||||
|
expandedId.value = expandedId.value === id ? null : id;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadTimers();
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
// состояние
|
||||||
|
timers,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
expandedId,
|
||||||
|
|
||||||
|
// методы
|
||||||
|
toggleExpand,
|
||||||
|
|
||||||
|
// иконки
|
||||||
timerOutline,
|
timerOutline,
|
||||||
chevronUp,
|
chevronUp,
|
||||||
chevronDown,
|
chevronDown,
|
||||||
@@ -24,44 +63,4 @@ export default {
|
|||||||
trashOutline,
|
trashOutline,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
timers: [],
|
|
||||||
expandedId: null,
|
|
||||||
loading: true,
|
|
||||||
error: null,
|
|
||||||
apiUrl: 'http://127.0.0.1:8090/api/timers'
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.fetchTimers();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async fetchTimers() {
|
|
||||||
try {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
// Для Tauri invoke (раскомментировать при необходимости)
|
|
||||||
// const { invoke } = window.__TAURI__.tauri;
|
|
||||||
// this.timers = await invoke('list_timers');
|
|
||||||
|
|
||||||
const response = await fetch(`${this.apiUrl}/`);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.timers = await response.json();
|
|
||||||
this.loading = false;
|
|
||||||
} catch (err) {
|
|
||||||
this.error = `Ошибка загрузки таймеров: ${err.message}`;
|
|
||||||
this.loading = false;
|
|
||||||
console.error('Fetch error:', err);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
toggleExpand(timerId) {
|
|
||||||
this.expandedId = this.expandedId === timerId ? null : timerId;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user