@beknurakhmed/webforge-cli 0.1.2 → 0.1.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beknurakhmed/webforge-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Interactive CLI to generate website project templates — landing pages, e-commerce, CRM, dashboards, blogs, portfolios with React, Vue, Angular, Next.js, Nuxt and more",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,15 +15,42 @@
15
15
  "outputPath": "dist",
16
16
  "index": "src/index.html",
17
17
  "browser": "src/main.ts",
18
+ "polyfills": ["zone.js"],
18
19
  "tsConfig": "tsconfig.json",
19
- "assets": ["{ \"glob\": \"**/*\", \"input\": \"public\" }"],
20
+ "assets": [
21
+ {
22
+ "glob": "**/*",
23
+ "input": "public"
24
+ }
25
+ ],
20
26
  "styles": ["src/styles.css"],
21
27
  "scripts": []
22
- }
28
+ },
29
+ "configurations": {
30
+ "production": {
31
+ "budgets": [
32
+ {
33
+ "type": "initial",
34
+ "maximumWarning": "500kB",
35
+ "maximumError": "1MB"
36
+ }
37
+ ],
38
+ "outputHashing": "all"
39
+ },
40
+ "development": {
41
+ "optimization": false,
42
+ "extractLicenses": false,
43
+ "sourceMap": true
44
+ }
45
+ },
46
+ "defaultConfiguration": "production"
23
47
  },
24
48
  "serve": {
25
49
  "builder": "@angular-devkit/build-angular:dev-server",
26
50
  "configurations": {
51
+ "production": {
52
+ "buildTarget": "app:build:production"
53
+ },
27
54
  "development": {
28
55
  "buildTarget": "app:build:development"
29
56
  }
@@ -7,4 +7,4 @@ bootstrapApplication(AppComponent, {
7
7
  providers: [
8
8
  provideRouter(routes),
9
9
  ],
10
- });
10
+ }).catch((err: unknown) => console.error(err));
@@ -5,4 +5,4 @@ import { routes } from './app/app.routes';
5
5
 
6
6
  bootstrapApplication(AppComponent, {
7
7
  providers: [provideRouter(routes)]
8
- });
8
+ }).catch((err) => console.error(err));
@@ -1,110 +1,62 @@
1
1
  'use client';
2
2
 
3
- import { useState } from 'react';
4
-
5
3
  interface Deal {
6
4
  id: number;
7
- title: string;
8
5
  company: string;
9
- value: string;
10
- stage: 'Qualification' | 'Proposal' | 'Negotiation' | 'Closed Won' | 'Closed Lost';
11
- probability: number;
6
+ value: number;
12
7
  contact: string;
13
- closeDate: string;
14
- icon: string;
8
+ stage: string;
15
9
  }
16
10
 
17
11
  const deals: Deal[] = [
18
- { id: 1, title: 'Enterprise License', company: 'TechCorp Inc.', value: '$45,000', stage: 'Negotiation', probability: 75, contact: 'Sarah Chen', closeDate: '2025-02-15', icon: '🏢' },
19
- { id: 2, title: 'Platform Migration', company: 'Innovate.io', value: '$28,000', stage: 'Proposal', probability: 50, contact: 'James Wilson', closeDate: '2025-03-01', icon: '🔄' },
20
- { id: 3, title: 'Design System', company: 'DesignLab Co.', value: '$15,000', stage: 'Qualification', probability: 25, contact: 'Maria Garcia', closeDate: '2025-03-15', icon: '🎨' },
21
- { id: 4, title: 'Premium Package', company: 'GlobalNet Ltd.', value: '$62,000', stage: 'Closed Won', probability: 100, contact: 'Robert Kim', closeDate: '2025-01-10', icon: '🎉' },
22
- { id: 5, title: 'Starter Plan', company: 'StartupXYZ', value: '$18,500', stage: 'Proposal', probability: 40, contact: 'Emily Brown', closeDate: '2025-02-28', icon: '🚀' },
23
- { id: 6, title: 'Consulting Retainer', company: 'Enterprise Solutions', value: '$8,200', stage: 'Closed Lost', probability: 0, contact: 'Michael Davis', closeDate: '2025-01-05', icon: '📋' },
12
+ { id: 1, company: 'TechCorp Inc.', value: 45000, contact: 'Sarah Chen', stage: 'Prospect' },
13
+ { id: 2, company: 'Innovate.io', value: 28000, contact: 'James Wilson', stage: 'Proposal' },
14
+ { id: 3, company: 'DesignLab Co.', value: 15000, contact: 'Maria Garcia', stage: 'Qualified' },
15
+ { id: 4, company: 'GlobalNet Ltd.', value: 62000, contact: 'Robert Kim', stage: 'Won' },
16
+ { id: 5, company: 'StartupXYZ', value: 18500, contact: 'Emily Brown', stage: 'Proposal' },
17
+ { id: 6, company: 'Oscorp Labs', value: 34000, contact: 'Michael Davis', stage: 'Prospect' },
18
+ { id: 7, company: 'LexCorp', value: 55000, contact: 'Rachel Green', stage: 'Qualified' },
19
+ { id: 8, company: 'Umbrella Co.', value: 21000, contact: 'Lisa Wang', stage: 'Won' },
24
20
  ];
25
21
 
26
- const stages = ['All', 'Qualification', 'Proposal', 'Negotiation', 'Closed Won', 'Closed Lost'];
22
+ const stages = ['Prospect', 'Qualified', 'Proposal', 'Won'];
27
23
 
28
24
  export default function DealsPage() {
29
- const [activeStage, setActiveStage] = useState('All');
30
-
31
- const filtered = activeStage === 'All' ? deals : deals.filter((d) => d.stage === activeStage);
32
25
  const pipelineTotal = deals
33
- .filter((d) => d.stage !== 'Closed Won' && d.stage !== 'Closed Lost')
34
- .reduce((sum, d) => sum + parseInt(d.value.replace(/[$,]/g, '')), 0);
26
+ .filter((d) => d.stage !== 'Won')
27
+ .reduce((sum, d) => sum + d.value, 0);
35
28
 
36
29
  return (
37
30
  <div className="page">
38
31
  <div className="page-header">
39
- <h1>Deals</h1>
40
- <p>Track your sales pipeline and deal progress.</p>
32
+ <h1>Deals Pipeline</h1>
33
+ <p>Pipeline value: ${pipelineTotal.toLocaleString()}</p>
41
34
  </div>
42
35
 
43
- <div className="deals-summary">
44
- <div className="deal-stat">
45
- <p className="deal-stat-value">{deals.length}</p>
46
- <p className="deal-stat-label">Total Deals</p>
47
- </div>
48
- <div className="deal-stat">
49
- <p className="deal-stat-value">${pipelineTotal.toLocaleString()}</p>
50
- <p className="deal-stat-label">Pipeline Value</p>
51
- </div>
52
- <div className="deal-stat">
53
- <p className="deal-stat-value">{deals.filter((d) => d.stage === 'Closed Won').length}</p>
54
- <p className="deal-stat-label">Won This Month</p>
55
- </div>
56
- <div className="deal-stat">
57
- <p className="deal-stat-value">{Math.round(deals.reduce((sum, d) => sum + d.probability, 0) / deals.length)}%</p>
58
- <p className="deal-stat-label">Avg. Probability</p>
59
- </div>
60
- </div>
61
-
62
- <div className="filter-group" style={{ marginBottom: '1.5rem' }}>
63
- {stages.map((stage) => (
64
- <button
65
- key={stage}
66
- className={`filter-btn ${activeStage === stage ? 'active' : ''}`}
67
- onClick={() => setActiveStage(stage)}
68
- >
69
- {stage}
70
- </button>
71
- ))}
72
- </div>
36
+ <div className="deals-board">
37
+ {stages.map((stage) => {
38
+ const stageDeals = deals.filter((d) => d.stage === stage);
39
+ const stageTotal = stageDeals.reduce((sum, d) => sum + d.value, 0);
73
40
 
74
- <div className="deals-grid">
75
- {filtered.map((deal) => (
76
- <div key={deal.id} className="deal-card">
77
- <div className="deal-card-header">
78
- <span className="deal-icon">{deal.icon}</span>
79
- <span className={`stage-badge ${deal.stage.toLowerCase().replace(' ', '-')}`}>{deal.stage}</span>
80
- </div>
81
- <h3 className="deal-title">{deal.title}</h3>
82
- <p className="deal-company">{deal.company}</p>
83
- <div className="deal-details">
84
- <div className="deal-detail">
85
- <span className="deal-label">Value</span>
86
- <span className="deal-value-text">{deal.value}</span>
87
- </div>
88
- <div className="deal-detail">
89
- <span className="deal-label">Contact</span>
90
- <span>{deal.contact}</span>
91
- </div>
92
- <div className="deal-detail">
93
- <span className="deal-label">Close Date</span>
94
- <span>{deal.closeDate}</span>
95
- </div>
96
- </div>
97
- <div className="deal-probability">
98
- <div className="probability-header">
99
- <span>Probability</span>
100
- <span>{deal.probability}%</span>
41
+ return (
42
+ <div key={stage} className="deals-column">
43
+ <div className="column-header">
44
+ <h3 className="column-title">{stage}</h3>
45
+ <span className="column-count">{stageDeals.length}</span>
101
46
  </div>
102
- <div className="probability-bar">
103
- <div className="probability-fill" style={{ width: `${deal.probability}%` }} />
47
+ <p className="column-total">${stageTotal.toLocaleString()}</p>
48
+ <div className="column-cards">
49
+ {stageDeals.map((deal) => (
50
+ <div key={deal.id} className="deal-card">
51
+ <h4 className="deal-company">{deal.company}</h4>
52
+ <p className="deal-value">${deal.value.toLocaleString()}</p>
53
+ <span className="deal-contact">👤 {deal.contact}</span>
54
+ </div>
55
+ ))}
104
56
  </div>
105
57
  </div>
106
- </div>
107
- ))}
58
+ );
59
+ })}
108
60
  </div>
109
61
  </div>
110
62
  );
@@ -101,31 +101,73 @@ a { text-decoration: none; color: inherit; }
101
101
  .status-badge.lead { background: #fef3c7; color: #d97706; }
102
102
  .status-badge.inactive { background: #f3f4f6; color: #6b7280; }
103
103
 
104
- /* Deals */
105
- .deals-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; margin-bottom: 2rem; }
106
- .deal-stat { background: var(--white); padding: 1.25rem; border-radius: var(--radius); box-shadow: var(--shadow); text-align: center; }
107
- .deal-stat-value { font-size: 1.5rem; font-weight: 800; color: var(--dark); }
108
- .deal-stat-label { font-size: 0.8rem; color: var(--text-light); margin-top: 0.25rem; }
109
- .deals-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 1.25rem; }
110
- .deal-card { background: var(--white); padding: 1.5rem; border-radius: var(--radius); box-shadow: var(--shadow); }
111
- .deal-card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; }
112
- .deal-icon { font-size: 1.5rem; }
113
- .stage-badge { padding: 0.2rem 0.6rem; border-radius: 20px; font-size: 0.7rem; font-weight: 600; }
114
- .stage-badge.qualification { background: #fef3c7; color: #d97706; }
115
- .stage-badge.proposal { background: #dbeafe; color: #2563eb; }
116
- .stage-badge.negotiation { background: #ede9fe; color: #7c3aed; }
117
- .stage-badge.closed-won { background: #d1fae5; color: #059669; }
118
- .stage-badge.closed-lost { background: #fee2e2; color: #dc2626; }
119
- .deal-title { font-size: 1.1rem; font-weight: 600; color: var(--dark); }
120
- .deal-company { font-size: 0.85rem; color: var(--text-light); margin-bottom: 1rem; }
121
- .deal-details { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1rem; }
122
- .deal-detail { display: flex; justify-content: space-between; font-size: 0.85rem; }
123
- .deal-label { color: var(--text-light); }
124
- .deal-value-text { font-weight: 600; color: var(--dark); }
125
- .deal-probability { margin-top: 0.5rem; }
126
- .probability-header { display: flex; justify-content: space-between; font-size: 0.8rem; color: var(--text-light); margin-bottom: 0.35rem; }
127
- .probability-bar { width: 100%; height: 6px; background: var(--bg); border-radius: 3px; overflow: hidden; }
128
- .probability-fill { height: 100%; background: var(--primary); border-radius: 3px; transition: width 0.3s; }
104
+ /* Deals Kanban Board */
105
+ .deals-board {
106
+ display: grid;
107
+ grid-template-columns: repeat(4, 1fr);
108
+ gap: 1.25rem;
109
+ min-height: 400px;
110
+ }
111
+ .deals-column {
112
+ background: var(--bg);
113
+ border-radius: var(--radius);
114
+ padding: 1rem;
115
+ }
116
+ .column-header {
117
+ display: flex;
118
+ justify-content: space-between;
119
+ align-items: center;
120
+ margin-bottom: 0.25rem;
121
+ }
122
+ .column-title {
123
+ font-size: 0.9rem;
124
+ font-weight: 700;
125
+ color: var(--dark);
126
+ }
127
+ .column-count {
128
+ background: var(--white);
129
+ color: var(--text-light);
130
+ font-size: 0.75rem;
131
+ font-weight: 600;
132
+ width: 24px;
133
+ height: 24px;
134
+ border-radius: 50%;
135
+ display: flex;
136
+ align-items: center;
137
+ justify-content: center;
138
+ }
139
+ .column-total {
140
+ font-size: 0.8rem;
141
+ color: var(--text-light);
142
+ margin-bottom: 1rem;
143
+ }
144
+ .column-cards {
145
+ display: flex;
146
+ flex-direction: column;
147
+ gap: 0.75rem;
148
+ }
149
+ .deal-card {
150
+ background: var(--white);
151
+ padding: 1rem;
152
+ border-radius: 8px;
153
+ box-shadow: var(--shadow);
154
+ }
155
+ .deal-company {
156
+ font-size: 0.95rem;
157
+ font-weight: 600;
158
+ color: var(--dark);
159
+ margin-bottom: 0.25rem;
160
+ }
161
+ .deal-value {
162
+ font-size: 1.1rem;
163
+ font-weight: 700;
164
+ color: var(--primary);
165
+ margin-bottom: 0.5rem;
166
+ }
167
+ .deal-contact {
168
+ font-size: 0.8rem;
169
+ color: var(--text-light);
170
+ }
129
171
 
130
172
  /* Settings */
131
173
  .settings-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: 1.5rem; }
@@ -160,6 +202,6 @@ a { text-decoration: none; color: inherit; }
160
202
  .sidebar-link { justify-content: center; padding: 0.75rem; }
161
203
  .crm-main { margin-left: 70px; padding: 1rem; }
162
204
  .dashboard-grid { grid-template-columns: 1fr; }
163
- .deals-grid { grid-template-columns: 1fr; }
205
+ .deals-board { grid-template-columns: repeat(2, 1fr); }
164
206
  .settings-grid { grid-template-columns: 1fr; }
165
207
  }
@@ -7,4 +7,4 @@ bootstrapApplication(AppComponent, {
7
7
  providers: [
8
8
  provideRouter(routes),
9
9
  ],
10
- });
10
+ }).catch((err: unknown) => console.error(err));