fix(test-app): resolve plugin detection and remove unused HomeViewSimple
- Fix System Status card to show correct plugin availability - Add automatic status check on component mount - Remove HomeViewSimple.vue (no longer needed) - Fix Vue 3 compatibility issues (@click.native removal) - Add comprehensive plugin diagnostics with all available plugins - Implement post-sync script to maintain capacitor.plugins.json - Add annotation processor for automatic plugin discovery The DailyNotification plugin now loads correctly and both System Status and Plugin Diagnostics show consistent, accurate information.
This commit is contained in:
@@ -40,6 +40,10 @@ dependencies {
|
|||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
|
||||||
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
|
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
|
||||||
implementation project(':capacitor-android')
|
implementation project(':capacitor-android')
|
||||||
|
|
||||||
|
// Capacitor annotation processor for automatic plugin discovery
|
||||||
|
annotationProcessor project(':capacitor-android')
|
||||||
|
|
||||||
testImplementation "junit:junit:$junitVersion"
|
testImplementation "junit:junit:$junitVersion"
|
||||||
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
||||||
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
||||||
|
|||||||
@@ -1,24 +1,10 @@
|
|||||||
package com.timesafari.dailynotification.test;
|
package com.timesafari.dailynotification.test;
|
||||||
|
|
||||||
import com.getcapacitor.BridgeActivity;
|
import com.getcapacitor.BridgeActivity;
|
||||||
import com.timesafari.dailynotification.DailyNotificationPlugin;
|
|
||||||
|
|
||||||
public class MainActivity extends BridgeActivity {
|
public class MainActivity extends BridgeActivity {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(android.os.Bundle savedInstanceState) {
|
public void onCreate(android.os.Bundle savedInstanceState) {
|
||||||
android.util.Log.d("MainActivity", "MainActivity.onCreate() called - START");
|
|
||||||
|
|
||||||
// Register the DailyNotification plugin BEFORE calling super.onCreate()
|
|
||||||
android.util.Log.d("MainActivity", "Registering DailyNotification plugin...");
|
|
||||||
try {
|
|
||||||
registerPlugin(DailyNotificationPlugin.class);
|
|
||||||
android.util.Log.d("MainActivity", "DailyNotification plugin registered successfully");
|
|
||||||
} catch (Exception e) {
|
|
||||||
android.util.Log.e("MainActivity", "Failed to register DailyNotification plugin", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
android.util.Log.d("MainActivity", "MainActivity.onCreate() - after super.onCreate()");
|
|
||||||
android.util.Log.d("MainActivity", "MainActivity.onCreate() called - END");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,4 +19,7 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':capacitor-android')
|
implementation project(':capacitor-android')
|
||||||
|
|
||||||
|
// Capacitor annotation processor for automatic plugin discovery
|
||||||
|
annotationProcessor project(':capacitor-android')
|
||||||
}
|
}
|
||||||
|
|||||||
58
test-apps/daily-notification-test/scripts/fix-capacitor-plugins.js
Executable file
58
test-apps/daily-notification-test/scripts/fix-capacitor-plugins.js
Executable file
@@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-sync script to fix capacitor.plugins.json
|
||||||
|
* This ensures the DailyNotification plugin is always registered
|
||||||
|
* even after npx cap sync overwrites the file
|
||||||
|
*
|
||||||
|
* @author Matthew Raymer
|
||||||
|
*/
|
||||||
|
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
|
const PLUGINS_JSON_PATH = path.join(__dirname, '../android/app/src/main/assets/capacitor.plugins.json');
|
||||||
|
|
||||||
|
const PLUGIN_ENTRY = {
|
||||||
|
name: "DailyNotification",
|
||||||
|
classpath: "com.timesafari.dailynotification.DailyNotificationPlugin"
|
||||||
|
};
|
||||||
|
|
||||||
|
function fixCapacitorPlugins() {
|
||||||
|
console.log('🔧 Fixing capacitor.plugins.json...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Read current content
|
||||||
|
let plugins = [];
|
||||||
|
if (fs.existsSync(PLUGINS_JSON_PATH)) {
|
||||||
|
const content = fs.readFileSync(PLUGINS_JSON_PATH, 'utf8');
|
||||||
|
plugins = JSON.parse(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if our plugin is already there
|
||||||
|
const hasPlugin = plugins.some(p => p.name === PLUGIN_ENTRY.name);
|
||||||
|
|
||||||
|
if (!hasPlugin) {
|
||||||
|
plugins.push(PLUGIN_ENTRY);
|
||||||
|
fs.writeFileSync(PLUGINS_JSON_PATH, JSON.stringify(plugins, null, 2));
|
||||||
|
console.log('✅ Added DailyNotification plugin to capacitor.plugins.json');
|
||||||
|
} else {
|
||||||
|
console.log('✅ DailyNotification plugin already exists in capacitor.plugins.json');
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error fixing capacitor.plugins.json:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run if called directly
|
||||||
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||||
|
fixCapacitorPlugins();
|
||||||
|
}
|
||||||
|
|
||||||
|
export { fixCapacitorPlugins };
|
||||||
@@ -36,7 +36,13 @@ class ActionCard extends Vue {
|
|||||||
@Prop({ type: Boolean, default: false }) loading!: boolean
|
@Prop({ type: Boolean, default: false }) loading!: boolean
|
||||||
|
|
||||||
handleClick() {
|
handleClick() {
|
||||||
if (!this.loading) this.$emit('click')
|
console.log('🔄 ActionCard handleClick called for:', this.title)
|
||||||
|
if (!this.loading) {
|
||||||
|
console.log('🔄 ActionCard emitting click event for:', this.title)
|
||||||
|
this.$emit('click')
|
||||||
|
} else {
|
||||||
|
console.log('🔄 ActionCard click ignored - loading state')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import HomeViewSimple from '../views/HomeViewSimple.vue'
|
import HomeView from '../views/HomeView.vue'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
@@ -7,7 +7,7 @@ const router = createRouter({
|
|||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'Home',
|
name: 'Home',
|
||||||
component: HomeViewSimple,
|
component: HomeView,
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Daily Notification Test',
|
title: 'Daily Notification Test',
|
||||||
requiresAuth: false
|
requiresAuth: false
|
||||||
|
|||||||
@@ -100,7 +100,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useAppStore } from '@/stores/app'
|
import { useAppStore } from '@/stores/app'
|
||||||
import ActionCard from '@/components/cards/ActionCard.vue'
|
import ActionCard from '@/components/cards/ActionCard.vue'
|
||||||
@@ -178,12 +178,49 @@ const navigateToSettings = (): void => {
|
|||||||
const checkSystemStatus = async (): Promise<void> => {
|
const checkSystemStatus = async (): Promise<void> => {
|
||||||
console.log('🔄 CLICK: Check System Status')
|
console.log('🔄 CLICK: Check System Status')
|
||||||
isCheckingStatus.value = true
|
isCheckingStatus.value = true
|
||||||
try {
|
|
||||||
// This will be handled by the app store
|
try {
|
||||||
console.log('🔧 Checking notification status...')
|
console.log('🔧 Checking system status...')
|
||||||
// For now, just log that we're checking
|
|
||||||
console.log('🔧 Status check completed (placeholder)')
|
// Use the same detection logic as runPluginDiagnostics
|
||||||
} finally {
|
const { Capacitor } = await import('@capacitor/core')
|
||||||
|
const platform = Capacitor.getPlatform()
|
||||||
|
const isNative = platform !== 'web'
|
||||||
|
|
||||||
|
if (isNative) {
|
||||||
|
console.log('🔧 Native platform detected, checking plugin availability...')
|
||||||
|
|
||||||
|
// Check if DailyNotification plugin is available
|
||||||
|
const plugin = (window as any).Capacitor?.Plugins?.DailyNotification
|
||||||
|
console.log('🔧 DailyNotification plugin check:', plugin ? 'Available' : 'Not Available')
|
||||||
|
|
||||||
|
if (plugin) {
|
||||||
|
console.log('✅ Plugin available, checking status...')
|
||||||
|
try {
|
||||||
|
const status = await plugin.checkStatus()
|
||||||
|
console.log('📊 Plugin status:', status)
|
||||||
|
|
||||||
|
// Update the app store status
|
||||||
|
appStore.setNotificationStatus(status)
|
||||||
|
console.log('✅ System status updated successfully')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Plugin status check failed:', error)
|
||||||
|
// Keep existing status or set error state
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn('⚠️ DailyNotification plugin not available')
|
||||||
|
// Reset to error state
|
||||||
|
appStore.setNotificationStatus(null)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('🌐 Web platform - plugin not available')
|
||||||
|
appStore.setNotificationStatus(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🔧 System status check completed')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ System status check failed:', error)
|
||||||
|
} finally {
|
||||||
isCheckingStatus.value = false
|
isCheckingStatus.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,6 +232,7 @@ const refreshSystemStatus = async (): Promise<void> => {
|
|||||||
|
|
||||||
const runPluginDiagnostics = async (): Promise<void> => {
|
const runPluginDiagnostics = async (): Promise<void> => {
|
||||||
console.log('🔄 CLICK: Plugin Diagnostics - METHOD CALLED!')
|
console.log('🔄 CLICK: Plugin Diagnostics - METHOD CALLED!')
|
||||||
|
console.log('🔄 FUNCTION START: runPluginDiagnostics called at', new Date().toISOString())
|
||||||
try {
|
try {
|
||||||
console.log('🔧 Running plugin diagnostics...')
|
console.log('🔧 Running plugin diagnostics...')
|
||||||
console.log('🔧 BUTTON CLICKED - METHOD CALLED!')
|
console.log('🔧 BUTTON CLICKED - METHOD CALLED!')
|
||||||
@@ -221,18 +259,44 @@ const runPluginDiagnostics = async (): Promise<void> => {
|
|||||||
if (plugin) {
|
if (plugin) {
|
||||||
console.log('✅ DailyNotification plugin available')
|
console.log('✅ DailyNotification plugin available')
|
||||||
|
|
||||||
|
// Get all available plugins
|
||||||
|
const allPlugins = Object.keys((window as any).Capacitor?.Plugins || {})
|
||||||
|
console.log('📋 All available plugins:', allPlugins)
|
||||||
|
|
||||||
// Test the checkStatus method
|
// Test the checkStatus method
|
||||||
try {
|
try {
|
||||||
const status = await plugin.checkStatus()
|
const status = await plugin.checkStatus()
|
||||||
console.log('📊 Plugin status check result:', status)
|
console.log('📊 Plugin status check result:', status)
|
||||||
alert(`✅ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: Yes\nStatus: ${JSON.stringify(status, null, 2)}`)
|
|
||||||
|
// Create detailed plugin report
|
||||||
|
const pluginReport = {
|
||||||
|
platform: platform,
|
||||||
|
nativePlatform: isNative,
|
||||||
|
dailyNotificationAvailable: true,
|
||||||
|
allAvailablePlugins: allPlugins,
|
||||||
|
dailyNotificationStatus: status,
|
||||||
|
capacitorVersion: (window as any).Capacitor?.getPlatform ? 'Available' : 'Unknown',
|
||||||
|
webViewInfo: {
|
||||||
|
userAgent: navigator.userAgent,
|
||||||
|
platform: navigator.platform
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alert(`✅ Plugin Diagnostics Complete!\n\n` +
|
||||||
|
`Platform: ${platform}\n` +
|
||||||
|
`Native Platform: ${isNative}\n` +
|
||||||
|
`DailyNotification Plugin: Available\n` +
|
||||||
|
`All Plugins (${allPlugins.length}): ${allPlugins.join(', ')}\n\n` +
|
||||||
|
`DailyNotification Status:\n${JSON.stringify(status, null, 2)}\n\n` +
|
||||||
|
`Full Report:\n${JSON.stringify(pluginReport, null, 2)}`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Plugin status check failed:', error)
|
console.error('❌ Plugin status check failed:', error)
|
||||||
alert(`⚠️ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: Yes\nStatus Check Failed: ${error}`)
|
alert(`⚠️ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nPlugin Available: Yes\nStatus Check Failed: ${error}\n\nAll Available Plugins: ${allPlugins.join(', ')}`)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn('⚠️ DailyNotification plugin not available')
|
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(', ')}`)
|
const allPlugins = Object.keys((window as any).Capacitor?.Plugins || {})
|
||||||
|
alert(`❌ Plugin Diagnostics Complete!\n\nPlatform: ${platform}\nDailyNotification Plugin: Not Available\n\nAll Available Plugins (${allPlugins.length}):\n${allPlugins.join(', ')}\n\nCapacitor Plugins Object:\n${JSON.stringify((window as any).Capacitor?.Plugins || {}, null, 2)}`)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('🌐 Running in web mode - plugin not available')
|
console.log('🌐 Running in web mode - plugin not available')
|
||||||
@@ -249,6 +313,12 @@ const openConsole = (): void => {
|
|||||||
console.log('📖 Console opened - check browser developer tools for detailed logs')
|
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.')
|
alert('📖 Console Logs\n\nOpen your browser\'s Developer Tools (F12) and check the Console tab for detailed diagnostic information.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize system status when component mounts
|
||||||
|
onMounted(async () => {
|
||||||
|
console.log('🏠 HomeView mounted - checking initial system status...')
|
||||||
|
await checkSystemStatus()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -1,258 +0,0 @@
|
|||||||
<!--
|
|
||||||
/**
|
|
||||||
* Simple Home View - Minimal Performance Version
|
|
||||||
*
|
|
||||||
* Simplified version to avoid main thread blocking
|
|
||||||
*
|
|
||||||
* @author Matthew Raymer
|
|
||||||
* @version 1.0.0
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="home-view">
|
|
||||||
<!-- Welcome Section -->
|
|
||||||
<div class="welcome-section">
|
|
||||||
<h1 class="welcome-title">
|
|
||||||
🔔 Daily Notification Test
|
|
||||||
</h1>
|
|
||||||
<p class="welcome-subtitle">
|
|
||||||
Vue 3 + vue-facing-decorator + Capacitor
|
|
||||||
</p>
|
|
||||||
<div class="platform-info">
|
|
||||||
<span class="platform-badge">
|
|
||||||
{{ platformName }}
|
|
||||||
</span>
|
|
||||||
<span class="status-badge">
|
|
||||||
{{ statusText }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Simple Actions -->
|
|
||||||
<div class="quick-actions">
|
|
||||||
<h2 class="section-title">Quick Actions</h2>
|
|
||||||
<div class="action-grid">
|
|
||||||
<div class="action-card" @click="navigateToSchedule">
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="card-icon">📅</div>
|
|
||||||
<div class="card-text">
|
|
||||||
<h3 class="card-title">Schedule Notification</h3>
|
|
||||||
<p class="card-description">Schedule a new daily notification</p>
|
|
||||||
</div>
|
|
||||||
<div class="card-arrow">→</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="action-card" @click="checkSystemStatus">
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="card-icon">📊</div>
|
|
||||||
<div class="card-text">
|
|
||||||
<h3 class="card-title">Check Status</h3>
|
|
||||||
<p class="card-description">View notification system status</p>
|
|
||||||
</div>
|
|
||||||
<div class="card-arrow">→</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="action-card" @click="runPluginDiagnostics">
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="card-icon">🔧</div>
|
|
||||||
<div class="card-text">
|
|
||||||
<h3 class="card-title">Plugin Diagnostics</h3>
|
|
||||||
<p class="card-description">Test plugin functionality</p>
|
|
||||||
</div>
|
|
||||||
<div class="card-arrow">→</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { Vue, Component, toNative } from 'vue-facing-decorator'
|
|
||||||
|
|
||||||
@Component
|
|
||||||
class HomeViewSimple extends Vue {
|
|
||||||
platformName = 'Android'
|
|
||||||
statusText = 'Ready'
|
|
||||||
|
|
||||||
navigateToSchedule() {}
|
|
||||||
checkSystemStatus() { alert('System status check - simplified version') }
|
|
||||||
runPluginDiagnostics() { alert('Plugin diagnostics - simplified version') }
|
|
||||||
}
|
|
||||||
export default toNative(HomeViewSimple)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.home-view {
|
|
||||||
padding: 20px;
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
min-height: 100vh;
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.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 16px 0;
|
|
||||||
font-size: 32px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-subtitle {
|
|
||||||
margin: 0 0 24px 0;
|
|
||||||
font-size: 18px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.platform-info {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 16px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.platform-badge, .status-badge {
|
|
||||||
padding: 8px 16px;
|
|
||||||
border-radius: 20px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.platform-badge {
|
|
||||||
background: rgba(76, 175, 80, 0.2);
|
|
||||||
color: #4caf50;
|
|
||||||
border: 1px solid rgba(76, 175, 80, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-badge {
|
|
||||||
background: rgba(33, 150, 243, 0.2);
|
|
||||||
color: #2196f3;
|
|
||||||
border: 1px solid rgba(33, 150, 243, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-actions {
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
margin: 0 0 24px 0;
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: white;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
||||||
gap: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-card {
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-card:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.15);
|
|
||||||
border-color: rgba(255, 255, 255, 0.3);
|
|
||||||
transform: translateY(-2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-icon {
|
|
||||||
font-size: 24px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-text {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-title {
|
|
||||||
margin: 0 0 4px 0;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-description {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-arrow {
|
|
||||||
flex-shrink: 0;
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mobile responsiveness */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.home-view {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-section {
|
|
||||||
padding: 30px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-title {
|
|
||||||
font-size: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-subtitle {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-card {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-content {
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-icon {
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-title {
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-description {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Reference in New Issue
Block a user