security: Add proper authentication, RBAC, and tenant isolation
- Add password hashing with bcrypt - Add AuthService with proper login - Add password strength validation - Add RBAC middleware (AdminOnly, ManagerOrAdmin) - Add tenant isolation middleware - Update CRM handler with tenant filtering - Add JWT fallback for development mode - Add user context helpers - Build successful
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import { useState } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import {
|
||||
Battery,
|
||||
Plus,
|
||||
Copy,
|
||||
Edit,
|
||||
FileText,
|
||||
Image,
|
||||
Video,
|
||||
Layout
|
||||
} from 'lucide-react';
|
||||
import { MarketingBattery as BatteryType } from '../types';
|
||||
import { mockBattery } from '../data/mockPlan';
|
||||
|
||||
const typeIcons = {
|
||||
campaign: Layout,
|
||||
template: FileText,
|
||||
cta: Plus,
|
||||
image_format: Image,
|
||||
video_format: Video,
|
||||
text_template: FileText
|
||||
};
|
||||
|
||||
export function MarketingBattery() {
|
||||
const [battery] = useState<BatteryType[]>(mockBattery);
|
||||
const [filter, setFilter] = useState<string>('all');
|
||||
|
||||
const filtered = filter === 'all'
|
||||
? battery
|
||||
: battery.filter(b => b.type === filter);
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold">Marketing Battery</h1>
|
||||
<p className="text-gray-500">Reusable campaigns, templates, and content formats</p>
|
||||
</div>
|
||||
<button className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
|
||||
<Plus size={18} />
|
||||
Add Asset
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Filters */}
|
||||
<div className="flex items-center gap-2">
|
||||
{['all', 'campaign', 'template', 'cta', 'image_format', 'video_format'].map(type => (
|
||||
<button
|
||||
key={type}
|
||||
onClick={() => setFilter(type)}
|
||||
className={`px-3 py-1.5 text-sm font-medium rounded-lg transition-colors capitalize ${
|
||||
filter === type ? 'bg-blue-600 text-white' : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
{type.replace('_', ' ')}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Battery Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{filtered.map(item => {
|
||||
const Icon = typeIcons[item.type] || Battery;
|
||||
return (
|
||||
<motion.div
|
||||
key={item.id}
|
||||
whileHover={{ scale: 1.02 }}
|
||||
className="bg-white border rounded-xl p-4"
|
||||
>
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 bg-blue-50 rounded-lg flex items-center justify-center">
|
||||
<Icon size={20} className="text-blue-600" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-medium">{item.name}</h3>
|
||||
<span className="text-xs text-gray-500 capitalize">{item.type.replace('_', ' ')}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<button className="p-1.5 hover:bg-gray-100 rounded">
|
||||
<Copy size={14} />
|
||||
</button>
|
||||
<button className="p-1.5 hover:bg-gray-100 rounded">
|
||||
<Edit size={14} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-gray-50 rounded-lg p-3 mb-3">
|
||||
<pre className="text-xs text-gray-600 overflow-auto">
|
||||
{JSON.stringify(item.content, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex gap-1">
|
||||
{item.tags.map(tag => (
|
||||
<span key={tag} className="px-2 py-0.5 bg-gray-100 text-gray-600 text-xs rounded">
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<span className="text-xs text-gray-500">
|
||||
Used {item.usageCount} times
|
||||
</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user