oceanhelm 0.0.8 → 0.0.9

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": "oceanhelm",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "Oceanhelm's highly customizable library",
5
5
  "private": false,
6
6
  "type": "module",
@@ -31,7 +31,7 @@
31
31
  "build:lib": "vite build --mode library",
32
32
  "preview": "vite preview",
33
33
  "prepublishOnly": "npm run build:lib",
34
- "test": "echo \"No tests specified\" && exit 0"
34
+ "test": "npm link"
35
35
  },
36
36
  "keywords": [
37
37
  "oceanhelm"
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="page-header d-flex justify-content-between align-items-center">
3
- <h2 style="margin-left: 20px;">{{ name }}</h2>
3
+ <h4 style="margin-left: 20px;">{{ name }}</h4>
4
4
  <div class="d-flex">
5
5
  <button class="btn btn-outline-primary me-2" @click="addUser()" v-if="this.userProfile.role == 'owner'">
6
6
  <i class="bi bi-bell"></i>
@@ -505,7 +505,7 @@ export default {
505
505
  { name: 'new-requisition', label: 'New Requisition', roles: ['requisitor'] },
506
506
  { name: 'my-requisitions', label: 'My Requisitions', roles: ['requisitor'] },
507
507
  { name: 'all-requisitions', label: 'All Requisitions', roles: ['requisitor', 'supervisor', 'captain', 'owner', 'purchaser'] },
508
- { name: 'approvals', label: 'Pending Approvals', roles: ['owner', 'supervisor', 'captain'] },
508
+ { name: 'approvals', label: 'Pending Approvals', roles: ['owner', 'supervisor'] },
509
509
  { name: 'purchasing', label: 'Purchasing Queue', roles: ['purchaser'] },
510
510
  { name: 'receiving', label: 'Receiving', roles: ['requisitor'] },
511
511
  { name: 'workflow', label: 'Workflow Guide', roles: ['requisitor', 'supervisor', 'owner', 'purchaser', 'captain'] }
@@ -2,7 +2,10 @@
2
2
  <!-- Fleet Summary -->
3
3
  <div class="row mb-3">
4
4
  <div class="col-md-4">
5
- <div class="card border-0 shadow-sm">
5
+ <div class="card border-0 shadow-sm"
6
+ @click="filterVessels('Active')"
7
+ :class="{ 'border-primary border-2': activeFilter === 'Active' }"
8
+ style="cursor: pointer;">
6
9
  <div class="card-body d-flex align-items-center">
7
10
  <div class="rounded-circle bg-primary bg-opacity-10 p-3 me-3">
8
11
  <i class="bi bi-check-circle-fill text-primary fs-4"></i>
@@ -15,7 +18,10 @@
15
18
  </div>
16
19
  </div>
17
20
  <div class="col-md-4">
18
- <div class="card border-0 shadow-sm">
21
+ <div class="card border-0 shadow-sm"
22
+ @click="filterVessels('Inactive')"
23
+ :class="{ 'border-secondary border-2': activeFilter === 'Inactive' }"
24
+ style="cursor: pointer;">
19
25
  <div class="card-body d-flex align-items-center">
20
26
  <div class="rounded-circle bg-secondary bg-opacity-10 p-3 me-3">
21
27
  <i class="bi bi-pause-circle-fill text-secondary fs-4"></i>
@@ -29,7 +35,7 @@
29
35
  </div>
30
36
  <!-- Register New Fleet -->
31
37
  <div class="col-md-4" v-if="canAddVessel">
32
- <div class="card border-0 shadow-sm" @click="handleAddVessel">
38
+ <div class="card border-0 shadow-sm" @click="handleAddVessel" style="cursor: pointer;">
33
39
  <div class="card-body d-flex align-items-center">
34
40
  <div class="rounded-circle bg-success bg-opacity-10 p-3 me-3">
35
41
  <i class="bi bi-patch-plus-fill text-success fs-4"></i>
@@ -42,7 +48,20 @@
42
48
  </div>
43
49
  </div>
44
50
 
45
- <h4 class="mb-4"><i class="bi bi-ship me-2"></i>Registered Vessels</h4>
51
+ <div class="d-flex justify-content-between align-items-center mb-4">
52
+ <h4 class="mb-0"><i class="bi bi-ship me-2"></i>Registered Vessels</h4>
53
+ <button
54
+ v-if="activeFilter !== 'All'"
55
+ class="btn btn-sm btn-outline-secondary"
56
+ @click="clearFilter">
57
+ <i class="bi bi-x-circle me-1"></i>Clear Filter
58
+ </button>
59
+ </div>
60
+
61
+ <!-- Filter indicator -->
62
+ <div v-if="activeFilter !== 'All'" class="alert alert-info mb-3" role="alert">
63
+ Showing <strong>{{ activeFilter }}</strong> vessels ({{ filteredVessels.length }})
64
+ </div>
46
65
 
47
66
  <!-- Loading State -->
48
67
  <div v-if="loading" class="text-center py-4">
@@ -53,16 +72,22 @@
53
72
  </div>
54
73
 
55
74
  <!-- Empty State -->
56
- <div v-else-if="!vessels.length" class="alert alert-primary" role="alert">
75
+ <div v-else-if="!filteredVessels.length && activeFilter === 'All'" class="alert alert-primary" role="alert">
57
76
  <h4 class="alert-heading">Empty Fleet!</h4>
58
77
  <p>You have an empty fleet, you have not added any vessel yet.</p>
59
78
  <hr>
60
79
  <p class="mb-0">Click on the add vessel button above, to start adding vessels to your fleet</p>
61
80
  </div>
62
81
 
82
+ <!-- No results for filter -->
83
+ <div v-else-if="!filteredVessels.length && activeFilter !== 'All'" class="alert alert-warning" role="alert">
84
+ <h4 class="alert-heading">No {{ activeFilter }} Vessels</h4>
85
+ <p class="mb-0">There are no {{ activeFilter.toLowerCase() }} vessels in your fleet.</p>
86
+ </div>
87
+
63
88
  <!-- Vessel Cards -->
64
89
  <div v-else class="row">
65
- <div class="col-lg-6" v-for="vessel in vessels" :key="vessel.registrationNumber || vessel.id">
90
+ <div class="col-lg-6" v-for="vessel in filteredVessels" :key="vessel.registrationNumber || vessel.id">
66
91
  <div class="vessel-card" @click="handleVesselClick(vessel)">
67
92
  <div class="card-body d-flex align-items-center">
68
93
  <div class="vessel-icon v-left">
@@ -151,6 +176,12 @@ export default {
151
176
  }
152
177
  },
153
178
 
179
+ data() {
180
+ return {
181
+ activeFilter: 'All' // 'All', 'Active', or 'Inactive'
182
+ };
183
+ },
184
+
154
185
  emits: [
155
186
  'vessel-add',
156
187
  'vessel-click',
@@ -171,6 +202,13 @@ export default {
171
202
  return this.vessels.filter(vessel => vessel.status === "Inactive").length;
172
203
  },
173
204
 
205
+ filteredVessels() {
206
+ if (this.activeFilter === 'All') {
207
+ return this.vessels;
208
+ }
209
+ return this.vessels.filter(vessel => vessel.status === this.activeFilter);
210
+ },
211
+
174
212
  canAddVessel() {
175
213
  return this.config.enableAdd &&
176
214
  (this.userProfile.role === 'owner' || this.userProfile.role === 'staff');
@@ -178,6 +216,15 @@ export default {
178
216
  },
179
217
 
180
218
  methods: {
219
+ // Filter methods
220
+ filterVessels(status) {
221
+ this.activeFilter = status;
222
+ },
223
+
224
+ clearFilter() {
225
+ this.activeFilter = 'All';
226
+ },
227
+
181
228
  // Event handlers that emit to parent
182
229
  handleAddVessel() {
183
230
  if (!this.canAddVessel) {
@@ -12,7 +12,7 @@ export const createSidebarConfig = (options = {}) => {
12
12
  export const defaultMenuItems = [
13
13
  {
14
14
  type: 'link',
15
- label: 'Dashboard',
15
+ label: 'Home',
16
16
  icon: 'bi bi-speedometer2',
17
17
  href: '/app/dashboard',
18
18
  active: true
@@ -26,8 +26,41 @@ export const defaultMenuItems = [
26
26
  },
27
27
  {
28
28
  type: 'text',
29
- label: 'Services'
29
+ label: 'Modules'
30
30
  },
31
+ {
32
+ type: 'dropdown',
33
+ label: 'Compliance',
34
+ icon: 'bi bi-list-ul',
35
+ children: [
36
+ {
37
+ label: 'Vessel Certification',
38
+ action: 'vessel-cert',
39
+ },
40
+ {
41
+ type: 'separator'
42
+ },
43
+ {
44
+ label: 'Crew Certification',
45
+ action: 'crew-cert'
46
+ },
47
+ {
48
+ type: 'separator'
49
+ },
50
+ {
51
+ label: 'Reports',
52
+ action: 'reports'
53
+ },
54
+ ]
55
+ },
56
+ /*
57
+ {
58
+ type: 'link',
59
+ label: 'Business Intelligence',
60
+ icon: 'bi bi-graph-up-arrow',
61
+ href: '/app/analytics'
62
+ },
63
+ */
31
64
  {
32
65
  type: 'button',
33
66
  label: 'Maintenance',