Refactor settings and task management, update API, and enhance type handling
- Replaced `username` and `password` fields with `accessKey` in `useSettings` for improved security. - Simplified task management in `useTasks`, adding `updateTasks` for bulk operations and refining API endpoint usage. - Updated `useApi` to dynamically use `VITE_API_URL` and switched to `Bearer` authentication. - Improved `Task` type definitions with renamed fields, nullable properties, and string-based timestamps. - Replaced `TaskStatus` enum values with string-based representations for better readability.
This commit is contained in:
@@ -1,12 +1,8 @@
|
|||||||
|
import type { Settings } from './useSettings.ts'
|
||||||
import { useCrypto } from './useCrypto.ts'
|
import { useCrypto } from './useCrypto.ts'
|
||||||
import { useStore } from './useStore.ts'
|
import { useStore } from './useStore.ts'
|
||||||
|
|
||||||
const BASE_URL = 'https://automation.deep-node.de/webhook'
|
const BASE_URL = import.meta.env.VITE_API_URL
|
||||||
|
|
||||||
interface Settings {
|
|
||||||
username: string
|
|
||||||
password: string
|
|
||||||
}
|
|
||||||
|
|
||||||
function isTauri() {
|
function isTauri() {
|
||||||
return typeof window !== 'undefined' && Boolean((window as typeof window & { __TAURI__?: unknown }).__TAURI__)
|
return typeof window !== 'undefined' && Boolean((window as typeof window & { __TAURI__?: unknown }).__TAURI__)
|
||||||
@@ -18,19 +14,18 @@ async function buildAuthHeader(): Promise<string | undefined> {
|
|||||||
const settings = await getValue<Settings>('settings')
|
const settings = await getValue<Settings>('settings')
|
||||||
if (!settings)
|
if (!settings)
|
||||||
return undefined
|
return undefined
|
||||||
let { username, password } = settings
|
let { accessKey } = settings
|
||||||
password = decrypt(password) as string
|
accessKey = decrypt(accessKey) as string
|
||||||
|
|
||||||
if (username && password) {
|
if (accessKey) {
|
||||||
const token = btoa(`${username}:${password}`)
|
return `Bearer ${accessKey}`
|
||||||
return `Basic ${token}`
|
|
||||||
}
|
}
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useApi() {
|
export function useApi() {
|
||||||
const apiFetch = async (endpoint: string, options: RequestInit = {}) => {
|
const apiFetch = async (endpoint: string, options: RequestInit = {}) => {
|
||||||
const url = endpoint.startsWith('http') ? endpoint : `${BASE_URL}/${endpoint}`
|
const url = endpoint.startsWith('http') ? endpoint : `${BASE_URL}${endpoint}`
|
||||||
|
|
||||||
const authHeader = await buildAuthHeader()
|
const authHeader = await buildAuthHeader()
|
||||||
const headers = {
|
const headers = {
|
||||||
@@ -62,13 +57,13 @@ export function useApi() {
|
|||||||
const post = (endpoint: string, body: unknown, options: RequestInit = {}) =>
|
const post = (endpoint: string, body: unknown, options: RequestInit = {}) =>
|
||||||
apiFetch(endpoint, { ...options, method: 'POST', body: JSON.stringify(body) })
|
apiFetch(endpoint, { ...options, method: 'POST', body: JSON.stringify(body) })
|
||||||
|
|
||||||
const put = (endpoint: string, body: unknown, options: RequestInit = {}) =>
|
const patch = (endpoint: string, body: unknown, options: RequestInit = {}) =>
|
||||||
apiFetch(endpoint, { ...options, method: 'PUT', body: JSON.stringify(body) })
|
apiFetch(endpoint, { ...options, method: 'PATCH', body: JSON.stringify(body) })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
get,
|
get,
|
||||||
post,
|
post,
|
||||||
put,
|
patch,
|
||||||
fetch: apiFetch,
|
fetch: apiFetch,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,12 @@ import { useCrypto } from './useCrypto.ts'
|
|||||||
import { useStore } from './useStore.ts'
|
import { useStore } from './useStore.ts'
|
||||||
|
|
||||||
export interface Settings {
|
export interface Settings {
|
||||||
username: string
|
accessKey: string
|
||||||
password: string
|
|
||||||
todayShown: boolean
|
todayShown: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingsDefault: Settings = {
|
const settingsDefault: Settings = {
|
||||||
username: '',
|
accessKey: '',
|
||||||
password: '',
|
|
||||||
todayShown: false,
|
todayShown: false,
|
||||||
}
|
}
|
||||||
const settings = ref<Settings>({ ...settingsDefault })
|
const settings = ref<Settings>({ ...settingsDefault })
|
||||||
@@ -26,31 +24,31 @@ export function useSettings() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let password = readSettings.password ?? ''
|
let accessKey = readSettings.accessKey ?? ''
|
||||||
if (password) {
|
if (accessKey) {
|
||||||
try {
|
try {
|
||||||
password = decrypt(password) as string
|
accessKey = decrypt(accessKey) as string
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.warn('Failed to decrypt stored password:', error)
|
console.warn('Failed to decrypt stored accessKey:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.value = {
|
settings.value = {
|
||||||
...settingsDefault,
|
...settingsDefault,
|
||||||
...readSettings,
|
...readSettings,
|
||||||
password,
|
accessKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveSettings = async () => {
|
const saveSettings = async () => {
|
||||||
const encryptedPassword = settings.value.password
|
const encryptedPassword = settings.value.accessKey
|
||||||
? encrypt(settings.value.password) as string
|
? encrypt(settings.value.accessKey) as string
|
||||||
: ''
|
: ''
|
||||||
|
|
||||||
await setValue<Settings>('settings', {
|
await setValue<Settings>('settings', {
|
||||||
...settings.value,
|
...settings.value,
|
||||||
password: encryptedPassword,
|
accessKey: encryptedPassword,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import type { Task } from '../types.ts'
|
import type { Task } from '../types.ts'
|
||||||
import { useArrayUnique } from '@vueuse/core'
|
import { useArrayUnique } from '@vueuse/core'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { TaskStatus } from '../types.ts'
|
|
||||||
import { useApi } from './useApi.ts'
|
import { useApi } from './useApi.ts'
|
||||||
|
|
||||||
const tasks = ref<Task[]>([])
|
const tasks = ref<Task[]>([])
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const error = ref<string | null>(null)
|
const error = ref<string | null>(null)
|
||||||
|
const endpoint = '/items/pomodays'
|
||||||
|
|
||||||
export function useTasks() {
|
export function useTasks() {
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
@@ -17,7 +17,7 @@ export function useTasks() {
|
|||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
error.value = null
|
error.value = null
|
||||||
try {
|
try {
|
||||||
const data = await api.get('e5880167-9322-4d7b-8a38-e06bae8a7734/list').then(res => res.json())
|
const data = await api.get(`${endpoint}?limit=-1`).then(res => res.json())
|
||||||
tasks.value = data.tasks ?? []
|
tasks.value = data.tasks ?? []
|
||||||
}
|
}
|
||||||
catch (e: any) {
|
catch (e: any) {
|
||||||
@@ -29,29 +29,12 @@ export function useTasks() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const createTask = async (taskData: Pick<Task, 'title' | 'dueDate' | 'tag'>) => {
|
const createTask = async (taskData: Pick<Task, 'title' | 'due_date' | 'tag'>) => {
|
||||||
// Get next ID as per current logic in CreateScreen.vue
|
|
||||||
const nextId = () => tasks.value.sort((a, b) => a.id_ - b.id_).reduce((acc, task) => {
|
|
||||||
if (task.id_ === acc + 1)
|
|
||||||
return acc + 1
|
|
||||||
return acc
|
|
||||||
}, 0) + 1
|
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
error.value = null
|
error.value = null
|
||||||
try {
|
try {
|
||||||
const newTask: Omit<Task, 'id'> = {
|
await api.post(endpoint, { ...taskData }).then(res => res.json())
|
||||||
id_: nextId(),
|
await fetchTasks()
|
||||||
status: TaskStatus.WAIT,
|
|
||||||
logs: [],
|
|
||||||
lastaction: Date.now(),
|
|
||||||
archived: false,
|
|
||||||
...taskData,
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await api.put('e5880167-9322-4d7b-8a38-e06bae8a7734/list', { tasks: [newTask] }).then(res => res.json())
|
|
||||||
if (data.tasks) {
|
|
||||||
tasks.value = data.tasks
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (e: any) {
|
catch (e: any) {
|
||||||
error.value = e.message || 'Failed to create task'
|
error.value = e.message || 'Failed to create task'
|
||||||
@@ -63,15 +46,29 @@ export function useTasks() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateTask = async (task: Task | Task[]) => {
|
const updateTask = async (task: Task) => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
error.value = null
|
error.value = null
|
||||||
const tasksToUpdate = (Array.isArray(task) ? task : [task]).map(t => ({ ...t, lastaction: Date.now() } as Task))
|
|
||||||
try {
|
try {
|
||||||
const data = await api.put('e5880167-9322-4d7b-8a38-e06bae8a7734/list', { tasks: tasksToUpdate }).then(res => res.json())
|
await api.patch(`${endpoint}/${task.id}`, task).then(res => res.json())
|
||||||
if (data.tasks) {
|
await fetchTasks()
|
||||||
tasks.value = data.tasks
|
|
||||||
}
|
}
|
||||||
|
catch (e: any) {
|
||||||
|
error.value = e.message || 'Failed to update task'
|
||||||
|
console.error('Error updating task:', e)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateTasks = async (data: Partial<Task>, keys: Task['id'][]) => {
|
||||||
|
isLoading.value = true
|
||||||
|
error.value = null
|
||||||
|
try {
|
||||||
|
await api.patch(`${endpoint}`, { data, keys }).then(res => res.json())
|
||||||
|
await fetchTasks()
|
||||||
}
|
}
|
||||||
catch (e: any) {
|
catch (e: any) {
|
||||||
error.value = e.message || 'Failed to update task'
|
error.value = e.message || 'Failed to update task'
|
||||||
@@ -92,6 +89,7 @@ export function useTasks() {
|
|||||||
fetchTasks,
|
fetchTasks,
|
||||||
createTask,
|
createTask,
|
||||||
updateTask,
|
updateTask,
|
||||||
|
updateTasks,
|
||||||
categories,
|
categories,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/types.ts
19
src/types.ts
@@ -1,24 +1,23 @@
|
|||||||
export enum TaskStatus {
|
export enum TaskStatus {
|
||||||
NONE,
|
ARCHIVE = 'archive',
|
||||||
DONE,
|
DONE = 'done',
|
||||||
WIP,
|
WIP = 'wip',
|
||||||
WAIT,
|
WAIT = 'wait',
|
||||||
FLAG,
|
FLAG = 'flag',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Worklog {
|
export interface Worklog {
|
||||||
start: number
|
start: string
|
||||||
end: number
|
end: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Task {
|
export interface Task {
|
||||||
archived: boolean
|
|
||||||
tag: string
|
tag: string
|
||||||
title: string
|
title: string
|
||||||
status: TaskStatus
|
status: TaskStatus
|
||||||
lastaction: number | null
|
lastaction: string | null
|
||||||
logs: Worklog[]
|
logs: Worklog[] | null
|
||||||
dueDate: number | null
|
due_date: string | null
|
||||||
id_: number
|
id_: number
|
||||||
id: number
|
id: number
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user