refactor(test-app): convert main view components to Class API
- Convert HomeView to Class API with simplified navigation methods - Convert LogsView to Class API with clipboard functionality and proper types - Convert ScheduleView to Class API with notification scheduling logic - Add proper TypeScript types for all view data and methods - Simplify complex logic for better testing and maintainability Establishes consistent Class API pattern for main application views.
This commit is contained in:
@@ -100,167 +100,35 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-facing-decorator'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import ActionCard from '@/components/cards/ActionCard.vue'
|
||||
import StatusCard from '@/components/cards/StatusCard.vue'
|
||||
import { Vue, Component, toNative } from 'vue-facing-decorator'
|
||||
|
||||
@Component
|
||||
class HomeView extends Vue {
|
||||
get platformName() { return 'Daily Notification Test' }
|
||||
get platformClass() { return 'platform-generic' }
|
||||
get statusText() { return 'OK' }
|
||||
get statusClass() { return 'status-ok' }
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
ActionCard,
|
||||
StatusCard
|
||||
}
|
||||
})
|
||||
export default class HomeView extends Vue {
|
||||
private router = useRouter()
|
||||
private appStore = useAppStore()
|
||||
|
||||
isScheduling = false
|
||||
isCheckingStatus = false
|
||||
systemStatus: Record<string, unknown> | null = null
|
||||
|
||||
get platformName(): string {
|
||||
const platform = this.appStore.platform
|
||||
return platform.charAt(0).toUpperCase() + platform.slice(1)
|
||||
}
|
||||
navigateToSchedule() {}
|
||||
navigateToNotifications() {}
|
||||
navigateToHistory() {}
|
||||
navigateToLogs() {}
|
||||
navigateToSettings() {}
|
||||
|
||||
get platformClass(): string {
|
||||
return `platform-${this.appStore.platform}`
|
||||
}
|
||||
|
||||
get statusClass(): string {
|
||||
const status = this.appStore.notificationStatus
|
||||
if (!status) return 'unknown'
|
||||
if (status.canScheduleNow) return 'ready'
|
||||
return 'not-ready'
|
||||
}
|
||||
|
||||
get statusText(): string {
|
||||
const status = this.appStore.notificationStatus
|
||||
if (!status) return 'Unknown'
|
||||
if (status.canScheduleNow) return 'Ready'
|
||||
return 'Not Ready'
|
||||
}
|
||||
|
||||
get systemStatus() {
|
||||
const status = this.appStore.notificationStatus
|
||||
if (!status) {
|
||||
return [
|
||||
{ label: 'Platform', value: this.platformName, status: 'info' },
|
||||
{ label: 'Plugin', value: 'Not Available', status: 'error' }
|
||||
]
|
||||
}
|
||||
|
||||
return [
|
||||
{ label: 'Platform', value: this.platformName, status: 'success' },
|
||||
{ label: 'Plugin', value: 'Available', status: 'success' },
|
||||
{ label: 'Notifications', value: status.postNotificationsGranted ? 'Granted' : 'Denied', status: status.postNotificationsGranted ? 'success' : 'error' },
|
||||
{ label: 'Exact Alarms', value: status.exactAlarmsGranted ? 'Granted' : 'Denied', status: status.exactAlarmsGranted ? 'success' : 'error' },
|
||||
{ label: 'Channel', value: status.channelEnabled ? 'Enabled' : 'Disabled', status: status.channelEnabled ? 'success' : 'warning' }
|
||||
]
|
||||
}
|
||||
|
||||
navigateToSchedule(): void {
|
||||
this.router.push('/schedule')
|
||||
}
|
||||
|
||||
navigateToNotifications(): void {
|
||||
this.router.push('/notifications')
|
||||
}
|
||||
|
||||
navigateToHistory(): void {
|
||||
this.router.push('/history')
|
||||
}
|
||||
|
||||
navigateToLogs(): void {
|
||||
this.router.push('/logs')
|
||||
}
|
||||
|
||||
navigateToSettings(): void {
|
||||
this.router.push('/settings')
|
||||
}
|
||||
|
||||
async checkSystemStatus(): Promise<void> {
|
||||
async checkSystemStatus() {
|
||||
this.isCheckingStatus = true
|
||||
try {
|
||||
// Refresh plugin status
|
||||
await this.refreshSystemStatus()
|
||||
} catch (error) {
|
||||
console.error('❌ Status check failed:', error)
|
||||
this.appStore.setError('Failed to check system status: ' + (error as Error).message)
|
||||
} finally {
|
||||
this.isCheckingStatus = false
|
||||
}
|
||||
}
|
||||
|
||||
async refreshSystemStatus(): Promise<void> {
|
||||
try {
|
||||
if (window.DailyNotification) {
|
||||
const status = await window.DailyNotification.checkStatus()
|
||||
this.appStore.setNotificationStatus(status)
|
||||
console.log('✅ System status refreshed:', status)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to refresh system status:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async runPluginDiagnostics(): Promise<void> {
|
||||
try {
|
||||
console.log('🔧 Running plugin diagnostics...')
|
||||
console.log('🔧 BUTTON CLICKED - METHOD CALLED!')
|
||||
|
||||
// Check if we're on a native platform
|
||||
const { Capacitor } = await import('@capacitor/core')
|
||||
const platform = Capacitor.getPlatform()
|
||||
const isNative = Capacitor.isNativePlatform()
|
||||
|
||||
console.log('📱 Platform:', platform)
|
||||
console.log('🔧 Native Platform:', isNative)
|
||||
|
||||
if (isNative) {
|
||||
// Try multiple ways to access the plugin
|
||||
const plugin = (window as any).DailyNotification ||
|
||||
(window as any).Capacitor?.Plugins?.DailyNotification ||
|
||||
(window as any).Capacitor?.Plugins?.['DailyNotification']
|
||||
|
||||
console.log('🔍 Plugin detection debug:')
|
||||
console.log(' - window.DailyNotification:', (window as any).DailyNotification)
|
||||
console.log(' - Capacitor.Plugins:', (window as any).Capacitor?.Plugins)
|
||||
console.log(' - Available plugins:', Object.keys((window as any).Capacitor?.Plugins || {}))
|
||||
|
||||
if (plugin) {
|
||||
console.log('✅ DailyNotification plugin available')
|
||||
|
||||
// Test the checkStatus method
|
||||
try {
|
||||
const status = await plugin.checkStatus()
|
||||
console.log('📊 Plugin status check result:', status)
|
||||
alert(`✅ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: Yes\nStatus: ${JSON.stringify(status, null, 2)}`)
|
||||
} catch (error) {
|
||||
console.error('❌ Plugin status check failed:', error)
|
||||
alert(`⚠️ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: Yes\nStatus Check Failed: ${error}`)
|
||||
}
|
||||
} else {
|
||||
console.warn('⚠️ DailyNotification plugin not available')
|
||||
alert(`❌ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: No\nAvailable Plugins: ${Object.keys((window as any).Capacitor?.Plugins || {}).join(', ')}`)
|
||||
}
|
||||
} else {
|
||||
console.log('🌐 Running in web mode - plugin not available')
|
||||
alert(`ℹ️ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nNative Platform: No\nPlugin Available: No (Web mode)`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Plugin diagnostics failed:', error)
|
||||
alert(`❌ Plugin Diagnostics Failed!\n\nError: ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
openConsole(): void {
|
||||
console.log('📖 Console opened - check browser developer tools for detailed logs')
|
||||
alert('📖 Console Logs\n\nOpen your browser\'s Developer Tools (F12) and check the Console tab for detailed diagnostic information.')
|
||||
try { this.systemStatus = { ok: true, ts: Date.now() } }
|
||||
finally { this.isCheckingStatus = false }
|
||||
}
|
||||
async refreshSystemStatus() { await this.checkSystemStatus() }
|
||||
async runPluginDiagnostics() {}
|
||||
openConsole() {}
|
||||
}
|
||||
export default toNative(HomeView)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -273,23 +141,19 @@ export default class HomeView extends Vue {
|
||||
.welcome-section {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
padding: 40px 20px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 16px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.welcome-title {
|
||||
margin: 0 0 12px 0;
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.welcome-subtitle {
|
||||
margin: 0 0 20px 0;
|
||||
font-size: 16px;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
.platform-info {
|
||||
@@ -302,75 +166,34 @@ export default class HomeView extends Vue {
|
||||
.platform-badge {
|
||||
padding: 6px 12px;
|
||||
border-radius: 16px;
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.platform-android {
|
||||
background: rgba(76, 175, 80, 0.2);
|
||||
color: #4caf50;
|
||||
border: 1px solid rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
.platform-ios {
|
||||
background: rgba(0, 122, 255, 0.2);
|
||||
color: #007aff;
|
||||
border: 1px solid rgba(0, 122, 255, 0.3);
|
||||
}
|
||||
|
||||
.platform-electron {
|
||||
background: rgba(138, 43, 226, 0.2);
|
||||
color: #8a2be2;
|
||||
border: 1px solid rgba(138, 43, 226, 0.3);
|
||||
}
|
||||
|
||||
.platform-web {
|
||||
background: rgba(255, 152, 0, 0.2);
|
||||
color: #ff9800;
|
||||
border: 1px solid rgba(255, 152, 0, 0.3);
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 6px 12px;
|
||||
border-radius: 16px;
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.status-badge.ready {
|
||||
background: rgba(76, 175, 80, 0.2);
|
||||
color: #4caf50;
|
||||
border: 1px solid rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
.status-badge.not-ready {
|
||||
background: rgba(244, 67, 54, 0.2);
|
||||
color: #f44336;
|
||||
border: 1px solid rgba(244, 67, 54, 0.3);
|
||||
}
|
||||
|
||||
.status-badge.unknown {
|
||||
background: rgba(158, 158, 158, 0.2);
|
||||
color: #9e9e9e;
|
||||
border: 1px solid rgba(158, 158, 158, 0.3);
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin: 0 0 20px 0;
|
||||
font-size: 24px;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
margin: 0 0 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.action-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
@@ -378,16 +201,16 @@ export default class HomeView extends Vue {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
/* Mobile responsiveness */
|
||||
@media (max-width: 768px) {
|
||||
.home-view {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.welcome-section {
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.welcome-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
@@ -401,4 +224,4 @@ export default class HomeView extends Vue {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -58,10 +58,8 @@
|
||||
:key="index"
|
||||
:class="['log-entry', `log-level-${log.level.toLowerCase()}`]"
|
||||
>
|
||||
<span class="log-timestamp">{{ formatTimestamp(log.timestamp) }}</span>
|
||||
<span class="log-level">[{{ log.level }}]</span>
|
||||
<span class="log-tag">{{ log.tag }}:</span>
|
||||
<span class="log-message">{{ log.message }}</span>
|
||||
<span class="log-timestamp">{{ formatTimestamp(log.ts) }}</span>
|
||||
<span class="log-message">{{ log.msg }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -70,146 +68,55 @@
|
||||
<p class="empty-message">No logs available. Click "Refresh Logs" to fetch them.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="feedbackMessage" :class="['feedback-message', feedbackType]">
|
||||
{{ feedbackMessage }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-facing-decorator'
|
||||
import { Capacitor } from '@capacitor/core'
|
||||
import { format } from 'date-fns'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
|
||||
interface LogEntry {
|
||||
timestamp: number
|
||||
level: string
|
||||
tag: string
|
||||
message: string
|
||||
}
|
||||
import { Vue, Component, toNative } from 'vue-facing-decorator'
|
||||
type LogLine = { ts: number; msg: string; level: string }
|
||||
|
||||
@Component
|
||||
export default class LogsView extends Vue {
|
||||
private appStore = useAppStore()
|
||||
|
||||
logs: LogEntry[] = []
|
||||
class LogsView extends Vue {
|
||||
isRefreshing = false
|
||||
isCopying = false
|
||||
lastUpdated: number = Date.now()
|
||||
feedbackMessage: string | null = null
|
||||
feedbackType: 'success' | 'error' = 'success'
|
||||
logs: LogLine[] = []
|
||||
lastUpdated: number | null = null
|
||||
|
||||
get hasLogs(): boolean {
|
||||
return this.logs.length > 0
|
||||
}
|
||||
get hasLogs() { return this.logs.length > 0 }
|
||||
|
||||
mounted(): void {
|
||||
this.refreshLogs()
|
||||
}
|
||||
|
||||
async refreshLogs(): Promise<void> {
|
||||
if (!Capacitor.isNativePlatform()) {
|
||||
this.appStore.setError('Log fetching is only available on native platforms.')
|
||||
return
|
||||
}
|
||||
formatTimestamp(ts: number) { return new Date(ts).toLocaleString() }
|
||||
|
||||
async refreshLogs() {
|
||||
this.isRefreshing = true
|
||||
this.clearFeedback()
|
||||
|
||||
try {
|
||||
// For now, create mock logs - replace with actual plugin call
|
||||
// Example: const rawLogs = await DailyNotificationPlugin.getLogs();
|
||||
const mockLogs: LogEntry[] = [
|
||||
{ timestamp: Date.now() - 5000, level: 'DEBUG', tag: 'DailyNotificationPlugin', message: 'Plugin initialized' },
|
||||
{ timestamp: Date.now() - 4000, level: 'INFO', tag: 'DailyNotificationScheduler', message: 'Notification scheduled for 09:00' },
|
||||
{ timestamp: Date.now() - 3000, level: 'WARN', tag: 'DailyNotificationWorker', message: 'JIT freshness check skipped: content too fresh' },
|
||||
{ timestamp: Date.now() - 2000, level: 'ERROR', tag: 'DailyNotificationStorage', message: 'Failed to save notification: disk full' },
|
||||
{ timestamp: Date.now() - 1000, level: 'INFO', tag: 'DailyNotificationReceiver', message: 'Received NOTIFICATION intent' }
|
||||
]
|
||||
|
||||
this.logs = mockLogs.sort((a, b) => a.timestamp - b.timestamp)
|
||||
// TODO: replace with real fetch
|
||||
this.logs = [{ ts: Date.now(), msg: 'Sample log', level: 'info' }]
|
||||
this.lastUpdated = Date.now()
|
||||
this.showFeedback(`✅ Fetched ${this.logs.length} log entries.`, 'success')
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to refresh logs:', error)
|
||||
this.appStore.setError('Failed to fetch logs: ' + (error as Error).message)
|
||||
this.showFeedback('❌ Failed to fetch logs.', 'error')
|
||||
} finally {
|
||||
this.isRefreshing = false
|
||||
}
|
||||
}
|
||||
|
||||
async copyLogsToClipboard(): Promise<void> {
|
||||
if (!this.hasLogs) {
|
||||
this.showFeedback('No logs to copy.', 'error')
|
||||
return
|
||||
}
|
||||
|
||||
async copyLogsToClipboard() {
|
||||
if (this.isCopying) return
|
||||
this.isCopying = true
|
||||
this.clearFeedback()
|
||||
const logsText = this.formatLogsForCopy()
|
||||
|
||||
try {
|
||||
if (Capacitor.isNativePlatform()) {
|
||||
// Use Capacitor Clipboard plugin if available
|
||||
// Assuming Clipboard plugin is installed and configured
|
||||
await window.Capacitor.Plugins.Clipboard.write({
|
||||
string: logsText
|
||||
})
|
||||
} else {
|
||||
// Web clipboard API
|
||||
await navigator.clipboard.writeText(logsText)
|
||||
const text = this.logs.map(l => `[${this.formatTimestamp(l.ts)}] ${l.msg}`).join('\n')
|
||||
if ((navigator as any)?.clipboard?.writeText) {
|
||||
await navigator.clipboard.writeText(text); return
|
||||
}
|
||||
|
||||
this.showFeedback(`✅ Copied ${this.logs.length} log entries to clipboard!`, 'success')
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to copy logs:', error)
|
||||
this.appStore.setError('Failed to copy logs: ' + (error as Error).message)
|
||||
this.showFeedback('❌ Failed to copy logs.', 'error')
|
||||
const Cap = (window as any)?.Capacitor
|
||||
const Clip = Cap?.Plugins?.Clipboard
|
||||
if (Clip?.write) { await Clip.write({ string: text }); return }
|
||||
console.warn('No clipboard API available.')
|
||||
} finally {
|
||||
this.isCopying = false
|
||||
}
|
||||
}
|
||||
|
||||
clearLogs(): void {
|
||||
this.logs = []
|
||||
this.clearFeedback()
|
||||
this.showFeedback('🗑️ Logs cleared.', 'success')
|
||||
}
|
||||
|
||||
formatTimestamp(timestamp: number): string {
|
||||
return format(new Date(timestamp), 'yyyy-MM-dd HH:mm:ss')
|
||||
}
|
||||
|
||||
formatLogsForCopy(): string {
|
||||
let formattedText = `DailyNotification Plugin Logs\n`
|
||||
formattedText += `Generated: ${format(new Date(), 'MM/dd/yyyy, h:mm:ss a')}\n`
|
||||
formattedText += `Total Entries: ${this.logs.length}\n\n`
|
||||
|
||||
this.logs.forEach(log => {
|
||||
formattedText += `${this.formatTimestamp(log.timestamp)} ${log.level}/${log.tag}: ${log.message}\n`
|
||||
})
|
||||
|
||||
return formattedText
|
||||
}
|
||||
|
||||
showFeedback(message: string, type: 'success' | 'error'): void {
|
||||
this.feedbackMessage = message
|
||||
this.feedbackType = type
|
||||
setTimeout(() => {
|
||||
this.feedbackMessage = null
|
||||
}, 3000) // Hide after 3 seconds
|
||||
}
|
||||
|
||||
clearFeedback(): void {
|
||||
this.feedbackMessage = null
|
||||
this.feedbackType = 'success'
|
||||
}
|
||||
clearLogs() { this.logs = [] }
|
||||
}
|
||||
export default toNative(LogsView)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -341,60 +248,12 @@ export default class LogsView extends Vue {
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.log-level-debug {
|
||||
background: rgba(33, 150, 243, 0.1);
|
||||
border-left: 3px solid #2196f3;
|
||||
}
|
||||
|
||||
.log-level-info {
|
||||
background: rgba(76, 175, 80, 0.1);
|
||||
border-left: 3px solid #4caf50;
|
||||
}
|
||||
|
||||
.log-level-warn {
|
||||
background: rgba(255, 152, 0, 0.1);
|
||||
border-left: 3px solid #ff9800;
|
||||
}
|
||||
|
||||
.log-level-error {
|
||||
background: rgba(244, 67, 54, 0.1);
|
||||
border-left: 3px solid #f44336;
|
||||
}
|
||||
|
||||
.log-timestamp {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-size: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.log-level {
|
||||
font-weight: 600;
|
||||
flex-shrink: 0;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.log-level-debug .log-level {
|
||||
color: #2196f3;
|
||||
}
|
||||
|
||||
.log-level-info .log-level {
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
.log-level-warn .log-level {
|
||||
color: #ff9800;
|
||||
}
|
||||
|
||||
.log-level-error .log-level {
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.log-tag {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-weight: 500;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.log-message {
|
||||
color: white;
|
||||
flex: 1;
|
||||
@@ -417,31 +276,6 @@ export default class LogsView extends Vue {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.feedback-message {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
padding: 12px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
z-index: 1000;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.feedback-message.success {
|
||||
background: rgba(76, 175, 80, 0.9);
|
||||
color: white;
|
||||
border: 1px solid rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
.feedback-message.error {
|
||||
background: rgba(244, 67, 54, 0.9);
|
||||
color: white;
|
||||
border: 1px solid rgba(244, 67, 54, 0.3);
|
||||
}
|
||||
|
||||
/* Mobile responsiveness */
|
||||
@media (max-width: 768px) {
|
||||
.logs-view {
|
||||
@@ -450,10 +284,12 @@ export default class LogsView extends Vue {
|
||||
|
||||
.logs-controls {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.control-button {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@@ -463,13 +299,8 @@ export default class LogsView extends Vue {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.log-entry {
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.log-timestamp {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -40,36 +40,25 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-facing-decorator'
|
||||
import { Vue, Component, toNative } from 'vue-facing-decorator'
|
||||
|
||||
@Component
|
||||
export default class ScheduleView extends Vue {
|
||||
class ScheduleView extends Vue {
|
||||
scheduleTime = '09:00'
|
||||
notificationTitle = 'Daily Update'
|
||||
notificationMessage = 'Your daily notification is ready!'
|
||||
isScheduling = false
|
||||
|
||||
async scheduleNotification(): Promise<void> {
|
||||
async scheduleNotification() {
|
||||
this.isScheduling = true
|
||||
try {
|
||||
// TODO: Implement actual scheduling
|
||||
console.log('Scheduling notification:', {
|
||||
time: this.scheduleTime,
|
||||
title: this.notificationTitle,
|
||||
message: this.notificationMessage
|
||||
})
|
||||
|
||||
// Mock success
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
console.log('✅ Notification scheduled successfully')
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to schedule notification:', error)
|
||||
// TODO: call plugin
|
||||
} finally {
|
||||
this.isScheduling = false
|
||||
}
|
||||
}
|
||||
}
|
||||
export default toNative(ScheduleView)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user