FrymasterBadgeApp/app.js

296 lines
9.9 KiB
JavaScript

/**
* DeComPress CMS - Core Admin Logic
*/
const state = {
currentView: 'Pages',
themes: [
{
id: 1,
name: 'Minimalist',
version: '1.2.0',
active: true,
color: 'bg-slate-300'
},
{
id: 2,
name: 'Dark Mode Pro',
version: '2.0.1',
active: false,
color: 'bg-gray-800'
},
{
id: 3,
name: 'Ocean Breeze',
version: '1.0.5',
active: false,
color: 'bg-blue-400'
}
],
customFields: [], // Dynamic state for the field builder
navItems: [
{ name: 'Pages', icon: '📄' },
{ name: 'Themes', icon: '🎨' },
{ name: 'Post Types', icon: '📌' },
{ name: 'Custom Fields', icon: '🔧' },
{ name: 'Users', icon: '👥' },
{ name: 'Roles', icon: '🛡️' },
{ name: 'Permissions', icon: '🔑' }
]
}
// --- Initialization ---
document.addEventListener('DOMContentLoaded', () => {
initApp()
})
function initApp () {
renderNav()
navigateTo(state.currentView)
// Mobile Toggle Logic
document.getElementById('mobile-toggle').addEventListener('click', () => {
const sidebar = document.getElementById('sidebar')
sidebar.classList.toggle('hidden')
sidebar.classList.toggle('absolute')
sidebar.classList.toggle('z-50')
sidebar.classList.toggle('h-full')
})
}
// --- Router ---
function navigateTo (viewName) {
state.currentView = viewName
document.getElementById('view-title').innerText = viewName
renderNav() // Refresh active state
const container = document.getElementById('app-content')
container.innerHTML = '' // Clear current
switch (viewName) {
case 'Pages':
container.innerHTML = viewPages()
break
case 'Themes':
container.innerHTML = viewThemes()
break
case 'Permissions':
container.innerHTML = viewPermissions()
break
case 'Custom Fields':
container.innerHTML = viewCustomFields()
break
case 'Users':
container.innerHTML = viewUsers()
break
default:
container.innerHTML = `<div class="p-10 text-center border-2 border-dashed rounded-lg text-gray-400">
${viewName} module is currently under construction.
</div>`
}
}
// --- Views ---
function viewPages () {
return `
<div class="bg-white rounded-xl shadow-sm border border-gray-200">
<table class="w-full text-left">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="p-4 font-semibold text-gray-600">Page Title</th>
<th class="p-4 font-semibold text-gray-600">Status</th>
<th class="p-4 font-semibold text-gray-600 text-right">Actions</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<tr><td class="p-4">Homepage</td><td class="p-4"><span class="bg-green-100 text-green-700 px-2 py-1 rounded text-xs">Published</span></td><td class="p-4 text-right text-blue-600 cursor-pointer">Edit</td></tr>
<tr><td class="p-4">Contact</td><td class="p-4"><span class="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-xs">Draft</span></td><td class="p-4 text-right text-blue-600 cursor-pointer">Edit</td></tr>
</tbody>
</table>
</div>
`
}
function viewThemes () {
return `
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
${state.themes
.map(
t => `
<div class="bg-white rounded-xl shadow-sm border-2 ${
t.active ? 'border-blue-500' : 'border-transparent'
} overflow-hidden">
<div class="h-32 ${t.color}"></div>
<div class="p-4">
<h4 class="font-bold">${t.name}</h4>
<p class="text-xs text-gray-500 mb-4">Version ${
t.version
}</p>
<button onclick="handleAction('Theme ${
t.name
} activated')" class="w-full py-2 rounded text-sm font-medium ${
t.active
? 'bg-blue-50 text-blue-600'
: 'bg-gray-100 hover:bg-gray-200 text-gray-700'
}">
${t.active ? 'Active' : 'Activate'}
</button>
</div>
</div>
`
)
.join('')}
</div>
`
}
function viewPermissions () {
const roles = ['Admin', 'Editor', 'Subscriber']
const caps = ['Update Core', 'Manage Themes', 'Delete Posts', 'Write Posts']
return `
<div class="bg-white rounded-xl shadow-sm overflow-hidden border border-gray-200">
<div class="overflow-x-auto">
<table class="w-full text-left">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="p-4 text-gray-600">Capability</th>
${roles
.map(
r =>
`<th class="p-4 text-center text-gray-600">${r}</th>`
)
.join('')}
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
${caps
.map(
c => `
<tr>
<td class="p-4 font-medium">${c}</td>
${roles
.map(
r =>
`<td class="p-4 text-center"><input type="checkbox" ${
r === 'Admin' ? 'checked' : ''
} class="w-4 h-4 rounded border-gray-300"></td>`
)
.join('')}
</tr>
`
)
.join('')}
</tbody>
</table>
</div>
</div>
`
}
function viewCustomFields () {
return `
<div class="max-w-4xl mx-auto">
<div class="flex justify-between items-center mb-6">
<h3 class="text-lg font-bold">Field Group: Blog Metadata</h3>
<button onclick="addField()" class="bg-blue-600 text-white px-4 py-2 rounded-lg text-sm hover:bg-blue-700 transition">+ Add Field</button>
</div>
<div id="fields-container" class="space-y-4">
${
state.customFields.length === 0
? '<p class="text-gray-400 italic text-center py-10">No fields added yet. Click "+ Add Field" to begin.</p>'
: ''
}
</div>
</div>
`
}
function viewUsers () {
return `
<div class="bg-white p-6 rounded-xl shadow-sm max-w-lg border border-gray-200">
<h3 class="font-bold mb-4">Invite New User</h3>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700">Email Address</label>
<input type="email" id="u-email" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm border p-2 focus:ring-blue-500 focus:border-blue-500">
</div>
<button onclick="handleUserInvite()" class="bg-slate-900 text-white w-full py-2 rounded-md font-medium hover:bg-black transition">Send Invitation</button>
</div>
</div>
`
}
// --- Component Logic ---
function renderNav () {
const nav = document.getElementById('main-nav')
nav.innerHTML = state.navItems
.map(
item => `
<button onclick="navigateTo('${item.name}')"
class="w-full flex items-center px-4 py-3 rounded-lg text-sm transition-colors ${
state.currentView === item.name
? 'bg-blue-600 text-white shadow-lg shadow-blue-900/20'
: 'text-gray-400 hover:bg-slate-800 hover:text-white'
}">
<span class="mr-3 text-lg">${item.icon}</span>
<span class="font-medium">${item.name}</span>
</button>
`
)
.join('')
}
function addField () {
const id = Date.now()
state.customFields.push({ id, label: '', type: 'text' })
refreshFields()
}
function removeField (id) {
state.customFields = state.customFields.filter(f => f.id !== id)
refreshFields()
}
function refreshFields () {
const container = document.getElementById('fields-container')
if (!container) return
container.innerHTML = state.customFields
.map(
(field, index) => `
<div class="bg-white p-4 rounded-lg border border-gray-200 shadow-sm flex items-center space-x-4 animate-in fade-in duration-300">
<div class="text-gray-300 cursor-move">☰</div>
<div class="flex-1 grid grid-cols-2 gap-4">
<input type="text" placeholder="Field Label" class="border rounded p-2 text-sm" value="${field.label}">
<select class="border rounded p-2 text-sm">
<option>Text</option>
<option>Textarea</option>
<option>Image</option>
<option>Boolean (Toggle)</option>
</select>
</div>
<button onclick="removeField(${field.id})" class="text-red-400 hover:text-red-600 p-2">✕</button>
</div>
`
)
.join('')
}
// --- General Handlers ---
function handleUserInvite () {
const email = document.getElementById('u-email').value
if (!email.includes('@')) {
alert('Please enter a valid email address.')
return
}
alert(`Invitation sent to ${email}`)
}
function handleAction (msg) {
console.log('CMS Action:', msg)
alert(msg)
}