one-for-all-framework 1.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +77 -19
- data/app/controllers/api_controller.rb +1 -1
- data/app/controllers/application_controller.rb +2 -2
- data/app/controllers/cart_controller.rb +52 -0
- data/app/controllers/dashboard_controller.rb +4 -3
- data/app/controllers/products_controller.rb +58 -0
- data/app/models/product.rb +8 -0
- data/app/views/cart_index.erb +112 -0
- data/app/views/cms/pages_form.erb +1 -1
- data/app/views/cms/pages_index.erb +61 -45
- data/app/views/cms/posts_form.erb +1 -1
- data/app/views/cms/posts_index.erb +54 -41
- data/app/views/cms/products_form.erb +89 -0
- data/app/views/cms/products_index.erb +129 -0
- data/app/views/cms/projects_form.erb +8 -8
- data/app/views/cms/projects_index.erb +47 -37
- data/app/views/dashboard.erb +18 -0
- data/app/views/docs.erb +180 -28
- data/app/views/index.erb +1 -1
- data/app/views/layout.erb +299 -20
- data/app/views/login.erb +1 -1
- data/app/views/product_show.erb +42 -0
- data/app/views/products_index.erb +40 -0
- data/bin/ofa +38 -9
- data/config/boot.rb +1 -0
- data/config/features.json +1 -1
- data/config/routes.rb +32 -0
- data/db/development.sqlite3 +0 -0
- data/db/migrations/20260502000000_create_products.rb +17 -0
- metadata +10 -1
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
<i class="fas fa-palette w-5"></i>
|
|
30
30
|
<span class="font-semibold">Projects</span>
|
|
31
31
|
</a>
|
|
32
|
+
<% elsif FEATURES_CONFIG['type'] == 'e_commerce' %>
|
|
33
|
+
<a href="/dashboard/products" class="flex items-center gap-3 px-4 py-3 rounded-2xl transition-all duration-300 <%= @req.path.start_with?('/dashboard/products') ? 'bg-primary text-white shadow-lg shadow-primary/30' : 'text-slate-500 hover:bg-white/5' %>">
|
|
34
|
+
<i class="fas fa-tag w-5"></i>
|
|
35
|
+
<span class="font-semibold">Products</span>
|
|
36
|
+
</a>
|
|
32
37
|
<% end %>
|
|
33
38
|
|
|
34
39
|
<div class="h-px bg-white/5 my-4"></div>
|
|
@@ -45,56 +50,64 @@
|
|
|
45
50
|
|
|
46
51
|
<!-- Main Content -->
|
|
47
52
|
<div class="flex-1 space-y-6 w-full">
|
|
48
|
-
<div class="flex justify-between items-center bg-white/5 p-6 rounded-3xl border border-white/5">
|
|
53
|
+
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 bg-white/5 p-6 rounded-3xl border border-white/5">
|
|
49
54
|
<div>
|
|
50
55
|
<h2 class="text-2xl font-black tracking-tight">Article Management</h2>
|
|
51
56
|
<p class="text-slate-500 text-sm">Write and manage your blog articles.</p>
|
|
52
57
|
</div>
|
|
53
|
-
<a href="/dashboard/posts/new" class="btn-premium">
|
|
58
|
+
<a href="/dashboard/posts/new" class="btn-premium w-full sm:w-auto text-center">
|
|
54
59
|
<i class="fas fa-plus mr-2 text-sm"></i> New Article
|
|
55
60
|
</a>
|
|
56
61
|
</div>
|
|
57
62
|
|
|
58
63
|
<div class="glass-panel overflow-hidden border-none shadow-xl">
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<
|
|
70
|
-
<
|
|
71
|
-
</
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
64
|
+
<!-- Header (Hidden on Mobile) -->
|
|
65
|
+
<div class="hidden md:grid grid-cols-12 bg-white/5 border-b border-white/5 text-slate-400 font-bold uppercase text-[10px] tracking-[0.2em] px-8 py-4">
|
|
66
|
+
<div class="col-span-8">Article Title</div>
|
|
67
|
+
<div class="col-span-2">Category</div>
|
|
68
|
+
<div class="col-span-2 text-right">Actions</div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="divide-y divide-white/5">
|
|
72
|
+
<% if @posts.empty? %>
|
|
73
|
+
<div class="px-8 py-20 text-center">
|
|
74
|
+
<div class="w-16 h-16 bg-white/5 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
75
|
+
<i class="fas fa-pen-nib text-2xl text-slate-600"></i>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="text-slate-500 italic">No articles created yet.</div>
|
|
78
|
+
</div>
|
|
79
|
+
<% end %>
|
|
80
|
+
<% @posts.each do |post| %>
|
|
81
|
+
<div class="grid grid-cols-1 md:grid-cols-12 items-center gap-4 md:gap-0 p-6 md:px-8 md:py-5 hover:bg-white/[0.02] transition-colors relative group">
|
|
82
|
+
<!-- Title -->
|
|
83
|
+
<div class="col-span-1 md:col-span-8">
|
|
84
|
+
<div class="flex flex-col">
|
|
85
|
+
<span class="font-black text-slate-700 dark:text-slate-200 group-hover:text-primary transition-colors text-lg md:text-base"><%= post.title %></span>
|
|
86
|
+
<span class="md:hidden text-[10px] text-slate-500 uppercase tracking-widest font-black mt-1">Article Title</span>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<!-- Category -->
|
|
91
|
+
<div class="col-span-1 md:col-span-2 flex flex-col">
|
|
92
|
+
<span class="text-xs bg-primary/10 px-3 py-1.5 rounded-xl text-primary w-fit font-bold"><%= post.category %></span>
|
|
93
|
+
<span class="md:hidden text-[10px] text-slate-500 uppercase tracking-widest font-black mt-2">Category</span>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<!-- Actions -->
|
|
97
|
+
<div class="col-span-1 md:col-span-2 flex justify-end gap-2 pt-4 md:pt-0 border-t md:border-none border-white/5">
|
|
98
|
+
<a href="/dashboard/posts/<%= post.id %>/edit" class="w-10 h-10 flex items-center justify-center rounded-2xl bg-primary/10 text-primary hover:bg-primary hover:text-white transition-all shadow-lg shadow-primary/10">
|
|
99
|
+
<i class="fas fa-edit text-sm"></i>
|
|
100
|
+
</a>
|
|
101
|
+
<form action="/dashboard/posts/<%= post.id %>/delete" method="POST" onsubmit="return confirm('Delete this article?')" class="inline">
|
|
102
|
+
<%= csrf_tag %>
|
|
103
|
+
<button type="submit" class="w-10 h-10 flex items-center justify-center rounded-2xl bg-red-500/10 text-red-500 hover:bg-red-500 hover:text-white transition-all shadow-lg shadow-red-500/10">
|
|
104
|
+
<i class="fas fa-trash-can text-sm"></i>
|
|
105
|
+
</button>
|
|
106
|
+
</form>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
<% end %>
|
|
110
|
+
</div>
|
|
98
111
|
</div>
|
|
99
112
|
</div>
|
|
100
113
|
</div>
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<div class="flex flex-col lg:flex-row gap-8 items-start">
|
|
2
|
+
<!-- CMS Sidebar -->
|
|
3
|
+
<aside class="glass-panel w-full lg:w-64 p-6 relative lg:sticky lg:top-24">
|
|
4
|
+
<div class="flex items-center gap-2 mb-8 px-2">
|
|
5
|
+
<div class="w-6 h-6 bg-primary rounded flex items-center justify-center text-white text-xs">
|
|
6
|
+
<i class="fas fa-user-shield"></i>
|
|
7
|
+
</div>
|
|
8
|
+
<h3 class="font-black tracking-tight text-lg">Admin<span class="text-primary">Panel</span></h3>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<nav class="space-y-2">
|
|
12
|
+
<a href="/dashboard" class="flex items-center gap-3 px-4 py-3 rounded-2xl transition-all duration-300 text-slate-500 hover:bg-white/5">
|
|
13
|
+
<i class="fas fa-chart-pie w-5"></i>
|
|
14
|
+
<span class="font-semibold">Dashboard</span>
|
|
15
|
+
</a>
|
|
16
|
+
|
|
17
|
+
<a href="/dashboard/products" class="flex items-center gap-3 px-4 py-3 rounded-2xl transition-all duration-300 bg-primary text-white shadow-lg shadow-primary/30">
|
|
18
|
+
<i class="fas fa-tag w-5"></i>
|
|
19
|
+
<span class="font-semibold">Products</span>
|
|
20
|
+
</a>
|
|
21
|
+
</nav>
|
|
22
|
+
</aside>
|
|
23
|
+
|
|
24
|
+
<!-- Main Content -->
|
|
25
|
+
<div class="flex-1 min-w-0 w-full pb-20">
|
|
26
|
+
<div class="glass-panel p-6 md:p-12 border-none shadow-2xl">
|
|
27
|
+
<div class="mb-10">
|
|
28
|
+
<h2 class="text-3xl font-black tracking-tight"><%= @product.id ? 'Edit Product' : 'New Product' %></h2>
|
|
29
|
+
<p class="text-slate-500">Fill in the details to list your product in the shop.</p>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<form action="<%= @product.id ? "/dashboard/products/#{@product.id}/update" : "/dashboard/products" %>" method="POST" class="space-y-8">
|
|
33
|
+
<%= csrf_tag %>
|
|
34
|
+
|
|
35
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
36
|
+
<div class="space-y-3">
|
|
37
|
+
<label class="text-sm font-black uppercase tracking-widest text-slate-400">Product Name</label>
|
|
38
|
+
<input type="text" name="product[name]" value="<%= @product.name %>" required
|
|
39
|
+
class="w-full bg-white/5 border border-white/10 rounded-2xl px-6 py-4 focus:border-primary focus:ring-1 focus:ring-primary outline-none transition-all font-bold">
|
|
40
|
+
</div>
|
|
41
|
+
<div class="space-y-3">
|
|
42
|
+
<label class="text-sm font-black uppercase tracking-widest text-slate-400">Category</label>
|
|
43
|
+
<input type="text" name="product[category]" value="<%= @product.category %>" placeholder="e.g. Digital, Physical, Services"
|
|
44
|
+
class="w-full bg-white/5 border border-white/10 rounded-2xl px-6 py-4 focus:border-primary focus:ring-1 focus:ring-primary outline-none transition-all font-bold">
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
49
|
+
<div class="space-y-3">
|
|
50
|
+
<label class="text-sm font-black uppercase tracking-widest text-slate-400">Price ($)</label>
|
|
51
|
+
<input type="number" step="0.01" name="product[price]" value="<%= @product.price %>" required
|
|
52
|
+
class="w-full bg-white/5 border border-white/10 rounded-2xl px-6 py-4 focus:border-primary focus:ring-1 focus:ring-primary outline-none transition-all font-bold">
|
|
53
|
+
</div>
|
|
54
|
+
<div class="space-y-3">
|
|
55
|
+
<label class="text-sm font-black uppercase tracking-widest text-slate-400">Stock Quantity</label>
|
|
56
|
+
<input type="number" name="product[stock]" value="<%= @product.stock %>" required
|
|
57
|
+
class="w-full bg-white/5 border border-white/10 rounded-2xl px-6 py-4 focus:border-primary focus:ring-1 focus:ring-primary outline-none transition-all font-bold">
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div class="space-y-3">
|
|
62
|
+
<label class="text-sm font-black uppercase tracking-widest text-slate-400">Image URL</label>
|
|
63
|
+
<div class="flex gap-4">
|
|
64
|
+
<input type="text" name="product[image_url]" id="image_url" value="<%= @product.image_url %>"
|
|
65
|
+
class="flex-1 bg-white/5 border border-white/10 rounded-2xl px-6 py-4 focus:border-primary focus:ring-1 focus:ring-primary outline-none transition-all font-bold">
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<div class="space-y-3">
|
|
70
|
+
<label class="text-sm font-black uppercase tracking-widest text-slate-400">Description (Markdown Supported)</label>
|
|
71
|
+
<textarea name="product[description]" rows="8" required
|
|
72
|
+
class="w-full bg-white/5 border border-white/10 rounded-2xl px-6 py-4 focus:border-primary focus:ring-1 focus:ring-primary outline-none transition-all font-medium"><%= @product.description %></textarea>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div class="flex items-center gap-4 p-4 bg-white/5 rounded-2xl border border-white/5">
|
|
76
|
+
<input type="checkbox" name="product[is_active]" value="1" <%= @product.is_active ? 'checked' : '' %> class="w-5 h-5 rounded border-white/10 text-primary focus:ring-primary">
|
|
77
|
+
<label class="text-sm font-bold text-slate-400">List product immediately in the shop</label>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<div class="flex flex-col sm:flex-row gap-4 pt-6">
|
|
81
|
+
<button type="submit" class="btn-premium flex-1 !py-5 order-2 sm:order-1">
|
|
82
|
+
<i class="fas fa-save mr-2"></i> <%= @product.id ? 'Update Product' : 'Create Product' %>
|
|
83
|
+
</button>
|
|
84
|
+
<a href="/dashboard/products" class="btn-secondary px-10 order-1 sm:order-2 text-center">Cancel</a>
|
|
85
|
+
</div>
|
|
86
|
+
</form>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<div class="flex flex-col md:flex-row gap-8 items-start">
|
|
2
|
+
<!-- CMS Sidebar -->
|
|
3
|
+
<aside class="glass-panel w-full md:w-64 p-6 sticky top-24">
|
|
4
|
+
<div class="flex items-center gap-2 mb-8 px-2">
|
|
5
|
+
<div class="w-6 h-6 bg-primary rounded flex items-center justify-center text-white text-xs">
|
|
6
|
+
<i class="fas fa-user-shield"></i>
|
|
7
|
+
</div>
|
|
8
|
+
<h3 class="font-black tracking-tight text-lg">Admin<span class="text-primary">Panel</span></h3>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<nav class="space-y-2">
|
|
12
|
+
<a href="/dashboard" class="flex items-center gap-3 px-4 py-3 rounded-2xl transition-all duration-300 <%= @req.path == '/dashboard' ? 'bg-primary text-white shadow-lg shadow-primary/30' : 'text-slate-500 hover:bg-white/5' %>">
|
|
13
|
+
<i class="fas fa-chart-pie w-5"></i>
|
|
14
|
+
<span class="font-semibold">Dashboard</span>
|
|
15
|
+
</a>
|
|
16
|
+
|
|
17
|
+
<a href="/dashboard/pages" class="flex items-center gap-3 px-4 py-3 rounded-2xl transition-all duration-300 <%= @req.path.start_with?('/dashboard/pages') ? 'bg-primary text-white shadow-lg shadow-primary/30' : 'text-slate-500 hover:bg-white/5' %>">
|
|
18
|
+
<i class="fas fa-file-lines w-5"></i>
|
|
19
|
+
<span class="font-semibold">Pages</span>
|
|
20
|
+
</a>
|
|
21
|
+
|
|
22
|
+
<% if FEATURES_CONFIG['type'] == 'blog' %>
|
|
23
|
+
<a href="/dashboard/posts" class="flex items-center gap-3 px-4 py-3 rounded-2xl transition-all duration-300 <%= @req.path.start_with?('/dashboard/posts') ? 'bg-primary text-white shadow-lg shadow-primary/30' : 'text-slate-500 hover:bg-white/5' %>">
|
|
24
|
+
<i class="fas fa-pen-nib w-5"></i>
|
|
25
|
+
<span class="font-semibold">Blog Posts</span>
|
|
26
|
+
</a>
|
|
27
|
+
<% elsif FEATURES_CONFIG['type'] == 'portfolio' %>
|
|
28
|
+
<a href="/dashboard/projects" class="flex items-center gap-3 px-4 py-3 rounded-2xl transition-all duration-300 <%= @req.path.start_with?('/dashboard/projects') ? 'bg-primary text-white shadow-lg shadow-primary/30' : 'text-slate-500 hover:bg-white/5' %>">
|
|
29
|
+
<i class="fas fa-palette w-5"></i>
|
|
30
|
+
<span class="font-semibold">Projects</span>
|
|
31
|
+
</a>
|
|
32
|
+
<% elsif FEATURES_CONFIG['type'] == 'e_commerce' %>
|
|
33
|
+
<a href="/dashboard/products" class="flex items-center gap-3 px-4 py-3 rounded-2xl transition-all duration-300 <%= @req.path.start_with?('/dashboard/products') ? 'bg-primary text-white shadow-lg shadow-primary/30' : 'text-slate-500 hover:bg-white/5' %>">
|
|
34
|
+
<i class="fas fa-tag w-5"></i>
|
|
35
|
+
<span class="font-semibold">Products</span>
|
|
36
|
+
</a>
|
|
37
|
+
<% end %>
|
|
38
|
+
|
|
39
|
+
<div class="h-px bg-white/5 my-4"></div>
|
|
40
|
+
|
|
41
|
+
<form action="/logout" method="POST">
|
|
42
|
+
<%= csrf_tag %>
|
|
43
|
+
<button type="submit" class="w-full flex items-center gap-3 px-4 py-3 rounded-2xl text-red-400 hover:bg-red-500/10 transition-all duration-300 font-semibold">
|
|
44
|
+
<i class="fas fa-door-open w-5"></i>
|
|
45
|
+
<span>Logout</span>
|
|
46
|
+
</button>
|
|
47
|
+
</form>
|
|
48
|
+
</nav>
|
|
49
|
+
</aside>
|
|
50
|
+
|
|
51
|
+
<!-- Main Content -->
|
|
52
|
+
<div class="flex-1 space-y-6 w-full min-w-0">
|
|
53
|
+
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 bg-white/5 p-6 rounded-3xl border border-white/5">
|
|
54
|
+
<div>
|
|
55
|
+
<h2 class="text-2xl font-black tracking-tight">Product Management</h2>
|
|
56
|
+
<p class="text-slate-500 text-sm">Manage your store products and inventory.</p>
|
|
57
|
+
</div>
|
|
58
|
+
<a href="/dashboard/products/new" class="btn-premium w-full sm:w-auto text-center">
|
|
59
|
+
<i class="fas fa-plus mr-2 text-sm"></i> New Product
|
|
60
|
+
</a>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div class="glass-panel overflow-hidden border-none shadow-xl">
|
|
64
|
+
<!-- Header (Hidden on Mobile) -->
|
|
65
|
+
<div class="hidden md:grid grid-cols-12 bg-white/5 border-b border-white/5 text-slate-400 font-bold uppercase text-[10px] tracking-[0.2em] px-8 py-4">
|
|
66
|
+
<div class="col-span-6">Product Information</div>
|
|
67
|
+
<div class="col-span-2">Price</div>
|
|
68
|
+
<div class="col-span-2 text-center">Stock</div>
|
|
69
|
+
<div class="col-span-2 text-right">Actions</div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div class="divide-y divide-white/5">
|
|
73
|
+
<% if @products.empty? %>
|
|
74
|
+
<div class="px-8 py-20 text-center">
|
|
75
|
+
<div class="w-16 h-16 bg-white/5 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
76
|
+
<i class="fas fa-box-open text-2xl text-slate-600"></i>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="text-slate-500 italic">No products found.</div>
|
|
79
|
+
</div>
|
|
80
|
+
<% end %>
|
|
81
|
+
<% @products.each do |product| %>
|
|
82
|
+
<div class="grid grid-cols-1 md:grid-cols-12 items-center gap-4 md:gap-0 p-6 md:px-8 md:py-5 hover:bg-white/[0.02] transition-colors relative group">
|
|
83
|
+
<!-- Info -->
|
|
84
|
+
<div class="col-span-1 md:col-span-6">
|
|
85
|
+
<div class="flex items-center gap-4">
|
|
86
|
+
<div class="w-12 h-12 rounded-xl overflow-hidden bg-slate-900/50 flex-shrink-0">
|
|
87
|
+
<img src="<%= product.image_url || '/images/logo.png' %>" class="w-full h-full object-cover">
|
|
88
|
+
</div>
|
|
89
|
+
<div class="flex flex-col">
|
|
90
|
+
<span class="font-black text-slate-700 dark:text-slate-200 group-hover:text-primary transition-colors text-lg md:text-base leading-tight"><%= product.name %></span>
|
|
91
|
+
<span class="text-[10px] text-slate-500 uppercase tracking-widest font-black mt-1"><%= product.category || 'Uncategorized' %></span>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<!-- Price -->
|
|
97
|
+
<div class="col-span-1 md:col-span-2 flex justify-between md:block items-center">
|
|
98
|
+
<span class="md:hidden text-[10px] text-slate-500 uppercase tracking-widest font-black">Price</span>
|
|
99
|
+
<span class="text-primary font-black text-xl md:text-base">$<%= product.price %></span>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<!-- Stock -->
|
|
103
|
+
<div class="col-span-1 md:col-span-2 flex justify-between md:block items-center">
|
|
104
|
+
<span class="md:hidden text-[10px] text-slate-500 uppercase tracking-widest font-black">Stock Level</span>
|
|
105
|
+
<div class="md:text-center">
|
|
106
|
+
<span class="px-3 py-1 rounded-full text-xs font-bold <%= product.stock.to_i < 5 ? 'bg-red-500/10 text-red-500' : 'bg-slate-500/10 text-slate-500' %>">
|
|
107
|
+
<%= product.stock %> units
|
|
108
|
+
</span>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<!-- Actions -->
|
|
113
|
+
<div class="col-span-1 md:col-span-2 flex justify-end gap-2 pt-4 md:pt-0 border-t md:border-none border-white/5">
|
|
114
|
+
<a href="/dashboard/products/<%= product.id %>/edit" class="w-10 h-10 flex items-center justify-center rounded-2xl bg-primary/10 text-primary hover:bg-primary hover:text-white transition-all shadow-lg shadow-primary/10">
|
|
115
|
+
<i class="fas fa-edit text-sm"></i>
|
|
116
|
+
</a>
|
|
117
|
+
<form action="/dashboard/products/<%= product.id %>/delete" method="POST" onsubmit="return confirm('Delete this product?')" class="inline">
|
|
118
|
+
<%= csrf_tag %>
|
|
119
|
+
<button type="submit" class="w-10 h-10 flex items-center justify-center rounded-2xl bg-red-500/10 text-red-500 hover:bg-red-500 hover:text-white transition-all shadow-lg shadow-red-500/10">
|
|
120
|
+
<i class="fas fa-trash-can text-sm"></i>
|
|
121
|
+
</button>
|
|
122
|
+
</form>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
<% end %>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<div class="flex flex-col
|
|
1
|
+
<div class="flex flex-col lg:flex-row gap-8 items-start">
|
|
2
2
|
<!-- CMS Sidebar -->
|
|
3
|
-
<aside class="glass-panel w-full
|
|
3
|
+
<aside class="glass-panel w-full lg:w-64 p-6 relative lg:sticky lg:top-24">
|
|
4
4
|
<div class="flex items-center gap-2 mb-8 px-2">
|
|
5
5
|
<div class="w-6 h-6 bg-primary rounded flex items-center justify-center text-white text-xs">
|
|
6
6
|
<i class="fas fa-user-shield"></i>
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
</aside>
|
|
45
45
|
|
|
46
46
|
<!-- Main Content -->
|
|
47
|
-
<div class="flex-1 space-y-6 w-
|
|
47
|
+
<div class="flex-1 space-y-6 pb-20 min-w-0 w-full">
|
|
48
48
|
<div class="flex justify-between items-center bg-white/5 p-6 rounded-3xl border border-white/5">
|
|
49
49
|
<div>
|
|
50
50
|
<h2 class="text-2xl font-black tracking-tight"><%= @project.id ? 'Edit' : 'Add' %> Project</h2>
|
|
@@ -55,17 +55,17 @@
|
|
|
55
55
|
</a>
|
|
56
56
|
</div>
|
|
57
57
|
|
|
58
|
-
<div class="glass-panel p-8">
|
|
58
|
+
<div class="glass-panel p-6 md:p-8">
|
|
59
59
|
<form action="<%= @project.id ? "/dashboard/projects/#{@project.id}/update" : "/dashboard/projects" %>" method="POST" id="main-form" class="space-y-6">
|
|
60
60
|
<%= csrf_tag %>
|
|
61
|
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
61
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 items-end">
|
|
62
62
|
<div class="space-y-2 text-left">
|
|
63
63
|
<label class="text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 ml-1">Project Name</label>
|
|
64
64
|
<input type="text" name="project[title]" value="<%= @project.title %>" placeholder="Example: E-Commerce Website" required oninput="generateSlug(this.value)"
|
|
65
65
|
class="w-full px-5 py-3 bg-white/5 border border-white/10 rounded-2xl focus:border-primary focus:ring-4 focus:ring-primary/10 outline-none transition-all text-slate-700 dark:text-slate-200 font-bold">
|
|
66
66
|
</div>
|
|
67
|
-
<div class="pb-
|
|
68
|
-
<label class="flex items-center gap-3 cursor-pointer group">
|
|
67
|
+
<div class="pb-2">
|
|
68
|
+
<label class="flex items-center gap-3 cursor-pointer group w-fit">
|
|
69
69
|
<div class="relative">
|
|
70
70
|
<input type="checkbox" name="project[is_active]" <%= @project.is_active ? 'checked' : '' %> class="sr-only peer">
|
|
71
71
|
<div class="w-11 h-6 bg-slate-200 dark:bg-white/10 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-green-500"></div>
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
</div>
|
|
103
103
|
<div id="image-preview-container" style="<%= @project.image_url && !@project.image_url.empty? ? '' : 'display: none;' %>" class="mt-4 p-2 border-2 border-dashed border-white/10 rounded-2xl text-left">
|
|
104
104
|
<span class="text-[10px] font-bold uppercase text-slate-500 mb-2 block ml-1">Project Preview</span>
|
|
105
|
-
<img id="image-preview" src="<%= @project.image_url %>" class="max-h-40 rounded-xl shadow-lg">
|
|
105
|
+
<img id="image-preview" src="<%= @project.image_url %>" class="max-h-40 max-w-full rounded-xl shadow-lg object-contain">
|
|
106
106
|
</div>
|
|
107
107
|
</div>
|
|
108
108
|
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
<i class="fas fa-palette w-5"></i>
|
|
30
30
|
<span class="font-semibold">Projects</span>
|
|
31
31
|
</a>
|
|
32
|
+
<% elsif FEATURES_CONFIG['type'] == 'e_commerce' %>
|
|
33
|
+
<a href="/dashboard/products" class="flex items-center gap-3 px-4 py-3 rounded-2xl transition-all duration-300 <%= @req.path.start_with?('/dashboard/products') ? 'bg-primary text-white shadow-lg shadow-primary/30' : 'text-slate-500 hover:bg-white/5' %>">
|
|
34
|
+
<i class="fas fa-tag w-5"></i>
|
|
35
|
+
<span class="font-semibold">Products</span>
|
|
36
|
+
</a>
|
|
32
37
|
<% end %>
|
|
33
38
|
|
|
34
39
|
<div class="h-px bg-white/5 my-4"></div>
|
|
@@ -45,52 +50,57 @@
|
|
|
45
50
|
|
|
46
51
|
<!-- Main Content -->
|
|
47
52
|
<div class="flex-1 space-y-6 w-full">
|
|
48
|
-
<div class="flex justify-between items-center bg-white/5 p-6 rounded-3xl border border-white/5">
|
|
53
|
+
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 bg-white/5 p-6 rounded-3xl border border-white/5">
|
|
49
54
|
<div>
|
|
50
55
|
<h2 class="text-2xl font-black tracking-tight">Project Management</h2>
|
|
51
56
|
<p class="text-slate-500 text-sm">Showcase your best work.</p>
|
|
52
57
|
</div>
|
|
53
|
-
<a href="/dashboard/projects/new" class="btn-premium">
|
|
58
|
+
<a href="/dashboard/projects/new" class="btn-premium w-full sm:w-auto text-center">
|
|
54
59
|
<i class="fas fa-plus mr-2 text-sm"></i> New Project
|
|
55
60
|
</a>
|
|
56
61
|
</div>
|
|
57
62
|
|
|
58
63
|
<div class="glass-panel overflow-hidden border-none shadow-xl">
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
<
|
|
69
|
-
<
|
|
70
|
-
</
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
64
|
+
<!-- Header (Hidden on Mobile) -->
|
|
65
|
+
<div class="hidden md:grid grid-cols-12 bg-white/5 border-b border-white/5 text-slate-400 font-bold uppercase text-[10px] tracking-[0.2em] px-8 py-4">
|
|
66
|
+
<div class="col-span-10">Project Title</div>
|
|
67
|
+
<div class="col-span-2 text-right">Actions</div>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div class="divide-y divide-white/5">
|
|
71
|
+
<% if @projects.empty? %>
|
|
72
|
+
<div class="px-8 py-20 text-center">
|
|
73
|
+
<div class="w-16 h-16 bg-white/5 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
74
|
+
<i class="fas fa-wand-magic-sparkles text-2xl text-slate-600"></i>
|
|
75
|
+
</div>
|
|
76
|
+
<div class="text-slate-500 italic">No projects created yet.</div>
|
|
77
|
+
</div>
|
|
78
|
+
<% end %>
|
|
79
|
+
<% @projects.each do |project| %>
|
|
80
|
+
<div class="grid grid-cols-1 md:grid-cols-12 items-center gap-4 md:gap-0 p-6 md:px-8 md:py-5 hover:bg-white/[0.02] transition-colors relative group">
|
|
81
|
+
<!-- Title -->
|
|
82
|
+
<div class="col-span-1 md:col-span-10">
|
|
83
|
+
<div class="flex flex-col">
|
|
84
|
+
<span class="font-black text-slate-700 dark:text-slate-200 group-hover:text-primary transition-colors text-lg md:text-base"><%= project.title %></span>
|
|
85
|
+
<span class="md:hidden text-[10px] text-slate-500 uppercase tracking-widest font-black mt-1">Project Name</span>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<!-- Actions -->
|
|
90
|
+
<div class="col-span-1 md:col-span-2 flex justify-end gap-2 pt-4 md:pt-0 border-t md:border-none border-white/5">
|
|
91
|
+
<a href="/dashboard/projects/<%= project.id %>/edit" class="w-10 h-10 flex items-center justify-center rounded-2xl bg-primary/10 text-primary hover:bg-primary hover:text-white transition-all shadow-lg shadow-primary/10">
|
|
92
|
+
<i class="fas fa-edit text-sm"></i>
|
|
93
|
+
</a>
|
|
94
|
+
<form action="/dashboard/projects/<%= project.id %>/delete" method="POST" onsubmit="return confirm('Delete this project?')" class="inline">
|
|
95
|
+
<%= csrf_tag %>
|
|
96
|
+
<button type="submit" class="w-10 h-10 flex items-center justify-center rounded-2xl bg-red-500/10 text-red-500 hover:bg-red-500 hover:text-white transition-all shadow-lg shadow-red-500/10">
|
|
97
|
+
<i class="fas fa-trash-can text-sm"></i>
|
|
98
|
+
</button>
|
|
99
|
+
</form>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
<% end %>
|
|
103
|
+
</div>
|
|
94
104
|
</div>
|
|
95
105
|
</div>
|
|
96
106
|
</div>
|
data/app/views/dashboard.erb
CHANGED
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
<i class="fas fa-palette w-5"></i>
|
|
30
30
|
<span class="font-semibold">Projects</span>
|
|
31
31
|
</a>
|
|
32
|
+
<% elsif FEATURES_CONFIG['type'] == 'e_commerce' %>
|
|
33
|
+
<a href="/dashboard/products" class="flex items-center gap-3 px-4 py-3 rounded-2xl transition-all duration-300 <%= @req.path.start_with?('/dashboard/products') ? 'bg-primary text-white shadow-lg shadow-primary/30' : 'text-slate-500 hover:bg-white/5' %>">
|
|
34
|
+
<i class="fas fa-tag w-5"></i>
|
|
35
|
+
<span class="font-semibold">Products</span>
|
|
36
|
+
</a>
|
|
32
37
|
<% end %>
|
|
33
38
|
|
|
34
39
|
<div class="h-px bg-white/5 my-4"></div>
|
|
@@ -86,6 +91,15 @@
|
|
|
86
91
|
<h4 class="text-xs font-black uppercase tracking-[0.2em] text-slate-400 mb-2">Total Projects</h4>
|
|
87
92
|
<div class="text-4xl font-black text-slate-700 dark:text-white tracking-tighter truncate"><%= @stats[:projects] %></div>
|
|
88
93
|
</div>
|
|
94
|
+
<% elsif @type == 'e_commerce' %>
|
|
95
|
+
<div class="glass-card !p-6 md:!p-8 group">
|
|
96
|
+
<div class="card-glow !bg-indigo-500/10"></div>
|
|
97
|
+
<div class="w-14 h-14 rounded-2xl bg-indigo-500/10 text-indigo-500 flex items-center justify-center mb-6 text-2xl group-hover:scale-110 group-hover:bg-indigo-500 group-hover:text-white transition-all duration-500 shadow-lg shadow-indigo-500/10">
|
|
98
|
+
<i class="fas fa-shopping-bag"></i>
|
|
99
|
+
</div>
|
|
100
|
+
<h4 class="text-xs font-black uppercase tracking-[0.2em] text-slate-400 mb-2">Shop Inventory</h4>
|
|
101
|
+
<div class="text-4xl font-black text-slate-700 dark:text-white tracking-tighter truncate"><%= @stats[:products] %></div>
|
|
102
|
+
</div>
|
|
89
103
|
<% end %>
|
|
90
104
|
|
|
91
105
|
<div class="glass-card !p-6 md:!p-8 group">
|
|
@@ -114,6 +128,10 @@
|
|
|
114
128
|
<a href="/dashboard/projects/new" class="px-8 py-3.5 rounded-2xl bg-white/5 border border-white/10 hover:bg-white/10 transition-all font-bold text-slate-700 dark:text-white flex items-center gap-2">
|
|
115
129
|
<i class="fas fa-wand-magic-sparkles mr-2"></i> New Project
|
|
116
130
|
</a>
|
|
131
|
+
<% elsif @type == 'e_commerce' %>
|
|
132
|
+
<a href="/dashboard/products/new" class="px-8 py-3.5 rounded-2xl bg-white/5 border border-white/10 hover:bg-white/10 transition-all font-bold text-slate-700 dark:text-white flex items-center gap-2">
|
|
133
|
+
<i class="fas fa-cart-plus mr-2"></i> New Product
|
|
134
|
+
</a>
|
|
117
135
|
<% end %>
|
|
118
136
|
</div>
|
|
119
137
|
</div>
|