765 lines
21 KiB
Markdown
765 lines
21 KiB
Markdown
# PDF Editor Step 3 - Joint Widget & Weldmap Entegrasyonu Roadmap
|
||
|
||
## 📋 Görev Özeti
|
||
|
||
**Amaç:** PDF çizimlerinde interaktif joint veri girişi sağlamak ve PDF Editor, Base Weldmap ve Weldlog veritabanları arasında iki yönlü entegrasyon kurmak.
|
||
|
||
**Temel Gereksinimler:**
|
||
1. Veri girişi için interaktif joint widget (popup)
|
||
2. Kayıt edilene kadar geçici veri depolama
|
||
3. Base Weldmap ve Weldlog ile SQL entegrasyonu
|
||
4. İki yönlü veri senkronizasyonu
|
||
5. Document Revision entegrasyonu (Spool Iso / As-Build)
|
||
|
||
---
|
||
|
||
## 🎯 Fonksiyonel Gereksinimler Özeti
|
||
|
||
### Senaryo 1: Engineering Iso + Adding Joints
|
||
- Kullanıcı PDF üzerine üçgen (Field) veya yuvarlak (Shop) çizer
|
||
- Veri girişi için widget otomatik açılır
|
||
- Veriler kayıt edilene kadar hafızada tutulur
|
||
- Kayıt sırasında: SQL ile Base Weldmap'e ekleme
|
||
- Çizimi Document Revision "Spool Iso" kısmına kaydet
|
||
|
||
### Senaryo 2: Spool Iso/Asbuild Iso + Adding Joints & Welder
|
||
- Kullanıcı mevcut joint üzerine gelir
|
||
- Widget önceden girilmiş verilerle açılır (Welder1-2 boş)
|
||
- Welder1-2 dropdown'larında uygun kaynakçıları listele
|
||
- PDF görüntüsünü güncelle: joint no (üstte), welder ID (altta), ayırıcı çizgi
|
||
- Kayıt sırasında: SQL ile Weldlog'u güncelle
|
||
- Çizimi Document Revision "As-Build" kısmına kaydet
|
||
|
||
### Senaryo 3: Veri Var ama Çizim Eksik
|
||
- Base Weldmap/Welder verisi var ama çizim eksik mi kontrol et
|
||
- Sol paneli aktifleştir: Spool No, Joint No, Welder ID bölümleri
|
||
- Kullanıcı Spool No seçer → Joint listesi
|
||
- Kullanıcı Joint + F/S şekli seçer → Çizim görünür
|
||
- Kullanıcı Joint + Welder + F/S şekli seçer → Welder ile çizim görünür
|
||
- Document Revision'a kaydet (Spool Iso veya As-Build)
|
||
|
||
---
|
||
|
||
## 🗺️ Geliştirme Roadmap'i
|
||
|
||
### Faz 1: Temel Yapı & Veri Yapısı (Hafta 1)
|
||
|
||
#### 1.1 Geçici Veri Depolama Sistemi
|
||
**Hedef:** Kaydedilmemiş joint verileri için hafıza içi veri depolama sistemi oluştur
|
||
|
||
**Görevler:**
|
||
- [ ] Geçici depolama için `JointDataManager` JavaScript sınıfı oluştur
|
||
- [ ] Veri yapısını uygula: `Map<shapeId, jointData>`
|
||
- [ ] Depolamadan önce veri doğrulama ekle
|
||
- [ ] Tarayıcı sessionStorage'da veri kalıcılığı (yedek)
|
||
- [ ] Sayfa kapanışında veri temizleme oluştur
|
||
|
||
**En İyi Uygulamalar:**
|
||
- O(1) arama performansı için Map kullan
|
||
- Çakışma çözümü için veri versiyonlama uygula
|
||
- Depolamadan önce veri doğrulama katmanı ekle
|
||
- Sayfa yenilemede hayatta kalması için sessionStorage kullan
|
||
|
||
**Oluşturulacak/Değiştirilecek Dosyalar:**
|
||
- `resources/views/admin/type/pdf-editor.blade.php` (JointDataManager sınıfı ekle)
|
||
- Oluştur: `public/js/pdf-editor/joint-data-manager.js` (opsiyonel ayrım)
|
||
|
||
#### 1.2 Widget Modal Geliştirmesi
|
||
**Hedef:** Mevcut joint widget modal'ını tüm gerekli alanlarla geliştir
|
||
|
||
**Görevler:**
|
||
- [ ] `joint-widget-modal.blade.php` dosyasını gözden geçir ve geliştir
|
||
- [ ] Edit type'a göre koşullu alan gösterimi ekle
|
||
- [ ] IC Log member seçimi uygula (Member1, Member2)
|
||
- [ ] IC Log'dan Material, Dia, NPS, Thickness için otomatik doldurma mantığı ekle
|
||
- [ ] Yeterliliğe göre welder dropdown filtreleme uygula
|
||
- [ ] Form doğrulama ekle
|
||
|
||
**En İyi Uygulamalar:**
|
||
- Dropdown'lar için Select2 kullan (projede mevcut)
|
||
- Member seçimi için debounced API çağrıları uygula
|
||
- Kademeli dropdown'lar uygula (member → material detayları)
|
||
- Asenkron işlemler için yükleme durumları ekle
|
||
- Bootstrap 5 form doğrulama kullan
|
||
|
||
**Değiştirilecek Dosyalar:**
|
||
- `resources/views/components/modals/joint-widget-modal.blade.php`
|
||
- `resources/views/admin/type/pdf-editor.blade.php` (widget entegrasyonu)
|
||
|
||
**Önemli Not:** Widget açılışı için **double-click** kullanılacak. Mevcut double-click silme özelliği kaldırılmalı veya farklı bir tuş kombinasyonu ile değiştirilmelidir.
|
||
|
||
---
|
||
|
||
### Phase 2: Shape Interaction & Widget Integration (Week 1-2)
|
||
|
||
#### 2.1 Shape Click/Hover Event Handling
|
||
**Goal:** Open widget when user interacts with joint shapes
|
||
|
||
**Tasks:**
|
||
- [ ] Add click event listener to triangle/circle shapes
|
||
- [ ] Add hover event listener for existing joints (Scenario 2)
|
||
- [ ] Position widget near clicked shape
|
||
- [ ] Load existing data if joint already has data
|
||
- [ ] Handle shape creation event (Scenario 1)
|
||
|
||
**Best Practices:**
|
||
- Use Fabric.js event delegation for performance
|
||
- Implement debouncing for hover events
|
||
- Calculate optimal widget position (avoid screen edges)
|
||
- Use requestAnimationFrame for smooth animations
|
||
- Add visual feedback (highlight shape on hover)
|
||
|
||
**Implementation:**
|
||
```javascript
|
||
// Shape click handler
|
||
fabricCanvas.on('mouse:down', (e) => {
|
||
if (e.target && (e.target.type === 'triangle' || e.target.type === 'circle')) {
|
||
if (currentEditType === 'adding_joints' || currentEditType === 'adding_joints_welder') {
|
||
openJointWidget(e.target, e.e);
|
||
}
|
||
}
|
||
});
|
||
|
||
// Hover handler for existing joints
|
||
fabricCanvas.on('mouse:over', (e) => {
|
||
if (e.target && e.target.shapeId && hasExistingData(e.target.shapeId)) {
|
||
showHoverTooltip(e.target);
|
||
}
|
||
});
|
||
```
|
||
|
||
#### 2.2 Widget Data Binding
|
||
**Goal:** Connect widget form with shape data
|
||
|
||
**Tasks:**
|
||
- [ ] Load shape data into widget form
|
||
- [ ] Save widget data to temporary storage
|
||
- [ ] Update shape label display (joint no, welder ID)
|
||
- [ ] Handle form field changes (real-time updates)
|
||
- [ ] Implement cancel/close behavior
|
||
|
||
**Best Practices:**
|
||
- Use two-way data binding pattern
|
||
- Implement reactive updates (update shape when form changes)
|
||
- Add unsaved changes warning
|
||
- Use event-driven architecture
|
||
|
||
**Files to Modify:**
|
||
- `resources/views/admin/type/pdf-editor.blade.php`
|
||
- `resources/views/components/modals/joint-widget-modal.blade.php`
|
||
|
||
---
|
||
|
||
### Phase 3: API Development & Database Integration (Week 2)
|
||
|
||
#### 3.1 API Endpoints for Joint Data
|
||
**Goal:** Create RESTful API endpoints for joint operations
|
||
|
||
**Tasks:**
|
||
- [ ] Create `saveJointData` endpoint (already exists, enhance)
|
||
- [ ] Create `getJointData` endpoint
|
||
- [ ] Create `checkExistingWeldmapData` endpoint (already exists)
|
||
- [ ] Create `getQualifiedWelders` endpoint
|
||
- [ ] Create `getICLogMembers` endpoint (already exists)
|
||
- [ ] Create `getICLogMemberDetails` endpoint (already exists)
|
||
|
||
**Best Practices:**
|
||
- Use Laravel Resource classes for consistent responses
|
||
- Implement proper validation rules
|
||
- Add error handling and logging
|
||
- Use database transactions for data integrity
|
||
- Implement rate limiting for API calls
|
||
|
||
**Files to Create/Modify:**
|
||
- `app/Http/Controllers/Api/AnnotationController.php` (enhance existing)
|
||
- `app/Http/Controllers/Api/PdfEditorLookupController.php` (enhance existing)
|
||
- `routes/web.php` (add routes if needed)
|
||
|
||
#### 3.2 Base Weldmap Integration
|
||
**Goal:** Insert/update joint data in Base Weldmap
|
||
|
||
**Tasks:**
|
||
- [ ] Map widget form data to weld_logs table structure
|
||
- [ ] Implement insert logic for new joints
|
||
- [ ] Implement update logic for existing joints
|
||
- [ ] Handle field mapping (widget → database)
|
||
- [ ] Add validation for required fields
|
||
- [ ] Implement batch insert for multiple joints
|
||
|
||
**Database Mapping:**
|
||
```
|
||
Widget Field → weld_logs Column
|
||
- joint_no → no_of_the_joint_as_per_as_built_survey
|
||
- type_of_joint → type_of_joint (F/S)
|
||
- welding_date → welding_date
|
||
- spool_no1 → spool_number_1
|
||
- spool_no2 → spool_number_2
|
||
- pose_no1 → pose_number_1
|
||
- pose_no2 → pose_number_2
|
||
- member1 → member_1
|
||
- member2 → member_2
|
||
- material → material_1, material_2
|
||
- dia1 → dia_1
|
||
- dia2 → dia_2
|
||
- nps1 → nps_1
|
||
- nps2 → nps_2
|
||
- thickness1 → thickness_1
|
||
- thickness2 → thickness_2
|
||
- welder_id1 → welder_1
|
||
- welder_id2 → welder_2
|
||
```
|
||
|
||
**Best Practices:**
|
||
- Use Eloquent models for database operations
|
||
- Implement database transactions
|
||
- Add rollback on error
|
||
- Use bulk insert for performance
|
||
- Validate data before database operations
|
||
|
||
**Files to Modify:**
|
||
- `app/Http/Controllers/Api/AnnotationController.php`
|
||
- `app/Models/WeldLog.php` (if needed)
|
||
|
||
#### 3.3 Weldlog Integration
|
||
**Goal:** Update welder assignments in Weldlog
|
||
|
||
**Tasks:**
|
||
- [ ] Implement welder assignment update logic
|
||
- [ ] Handle real_welder_1 and real_welder_2 fields
|
||
- [ ] Update joint display on PDF after assignment
|
||
- [ ] Validate welder qualifications before assignment
|
||
|
||
**Best Practices:**
|
||
- Use updateOrCreate for idempotent operations
|
||
- Implement soft validation (warnings, not errors)
|
||
- Add audit trail for welder changes
|
||
- Use database transactions
|
||
|
||
**Files to Modify:**
|
||
- `app/Http/Controllers/Api/AnnotationController.php`
|
||
- `app/Models/WeldLog.php`
|
||
|
||
---
|
||
|
||
### Phase 4: Two-Way Data Synchronization (Week 2-3)
|
||
|
||
#### 4.1 Data Existence Check
|
||
**Goal:** Check if Base Weldmap/Welder data exists but drawing is missing
|
||
|
||
**Tasks:**
|
||
- [ ] Create API endpoint to check data existence
|
||
- [ ] Implement left panel activation logic
|
||
- [ ] Create Spool No dropdown population
|
||
- [ ] Create Joint No dropdown (filtered by Spool)
|
||
- [ ] Create Welder ID dropdown (filtered by Joint)
|
||
|
||
**API Endpoint:**
|
||
```php
|
||
GET /api/pdf-editor/check-existing-weldmap
|
||
Query: drawing_number
|
||
Response: {
|
||
has_data: true/false,
|
||
spools: [...],
|
||
joints: [...],
|
||
welders: [...]
|
||
}
|
||
```
|
||
|
||
**Best Practices:**
|
||
- Cache API responses for performance
|
||
- Implement pagination for large datasets
|
||
- Use eager loading for relationships
|
||
- Add loading states in UI
|
||
|
||
**Files to Create/Modify:**
|
||
- `app/Http/Controllers/Api/PdfEditorLookupController.php`
|
||
- `resources/views/admin/type/pdf-editor.blade.php` (left panel)
|
||
|
||
#### 4.2 Drawing Generation from Data
|
||
**Goal:** Generate PDF drawing shapes from existing database data
|
||
|
||
**Tasks:**
|
||
- [ ] Implement shape creation from joint data
|
||
- [ ] Position shapes based on joint relationships
|
||
- [ ] Add welder labels if welder data exists
|
||
- [ ] Handle F/S shape selection
|
||
- [ ] Update annotation storage
|
||
|
||
**Best Practices:**
|
||
- Use Fabric.js for shape creation
|
||
- Implement smart positioning algorithm
|
||
- Add collision detection
|
||
- Use canvas grouping for related shapes
|
||
|
||
**Files to Modify:**
|
||
- `resources/views/admin/type/pdf-editor.blade.php`
|
||
|
||
---
|
||
|
||
### Phase 5: Document Revision Integration (Week 3)
|
||
|
||
#### 5.1 Save to Spool Iso
|
||
**Goal:** Save annotated PDF to Document Revision "Spool Iso"
|
||
|
||
**Tasks:**
|
||
- [ ] Implement PDF export with annotations
|
||
- [ ] Save to Document Revision pdf_spool_iso column
|
||
- [ ] Update revision metadata
|
||
- [ ] Handle versioning
|
||
|
||
**Best Practices:**
|
||
- Use existing PDF export functionality
|
||
- Implement async save operation
|
||
- Add progress indicator
|
||
- Handle save errors gracefully
|
||
|
||
**Files to Modify:**
|
||
- `app/Http/Controllers/Api/AnnotationController.php`
|
||
- `app/Http/Controllers/Api/PdfEditorLookupController.php` (updateDocumentStage)
|
||
|
||
#### 5.2 Save to As-Build
|
||
**Goal:** Save annotated PDF to Document Revision "As-Build"
|
||
|
||
**Tasks:**
|
||
- [ ] Similar to Spool Iso but for pdf_as_build column
|
||
- [ ] Include welder information in saved PDF
|
||
- [ ] Update revision metadata
|
||
|
||
**Files to Modify:**
|
||
- Same as 5.1
|
||
|
||
---
|
||
|
||
### Phase 6: Welder Qualification Filtering (Week 3)
|
||
|
||
#### 6.1 Welder Qualification System
|
||
**Goal:** Filter welders based on qualifications and validity
|
||
|
||
**Tasks:**
|
||
- [ ] Integrate with existing Welder Assignment system
|
||
- [ ] Implement qualification filtering logic
|
||
- [ ] Check welder expiry dates
|
||
- [ ] Filter by material compatibility
|
||
- [ ] Filter by welding method
|
||
|
||
**Best Practices:**
|
||
- Reuse existing welder assignment logic
|
||
- Cache qualification data
|
||
- Implement client-side filtering for performance
|
||
- Add server-side validation
|
||
|
||
**Files to Modify:**
|
||
- `app/Http/Controllers/Api/PdfEditorLookupController.php`
|
||
- `app/Http/Controllers/AutoCompleteType/welder-assignment/welder_1.php` (reference)
|
||
|
||
---
|
||
|
||
## 🔧 Technical Architecture
|
||
|
||
### Frontend Architecture
|
||
|
||
```
|
||
PDF Editor Canvas (Fabric.js)
|
||
↓
|
||
Shape Event Handlers
|
||
↓
|
||
Joint Data Manager (Temporary Storage)
|
||
↓
|
||
Widget Modal (Form)
|
||
↓
|
||
API Calls (AJAX)
|
||
↓
|
||
Backend Controllers
|
||
↓
|
||
Database (weld_logs, annotations, document_revisions)
|
||
```
|
||
|
||
### Data Flow
|
||
|
||
**Scenario 1: New Joint Creation**
|
||
```
|
||
User draws shape → Widget opens → User fills form →
|
||
Data stored in memory → User clicks Save →
|
||
Batch insert to weld_logs → Save PDF to Document Revision
|
||
```
|
||
|
||
**Scenario 2: Welder Assignment**
|
||
```
|
||
User hovers joint → Widget opens (pre-filled) →
|
||
User selects welders → Update memory →
|
||
User clicks Save → Update weld_logs →
|
||
Update PDF display → Save PDF to Document Revision
|
||
```
|
||
|
||
**Scenario 3: Drawing from Data**
|
||
```
|
||
Check data exists → Activate left panel →
|
||
User selects Spool → Joints list →
|
||
User selects Joint + Shape → Create shape on PDF →
|
||
Save PDF to Document Revision
|
||
```
|
||
|
||
---
|
||
|
||
## 📚 Best Practices & Recommendations
|
||
|
||
### 1. Temporary Data Storage
|
||
|
||
**Option A: In-Memory (Recommended)**
|
||
- Use JavaScript Map/Object for fast access
|
||
- Store in component state
|
||
- Clear on page unload
|
||
- **Pros:** Fast, no persistence needed
|
||
- **Cons:** Lost on page refresh
|
||
|
||
**Option B: SessionStorage**
|
||
- Use browser sessionStorage API
|
||
- Survives page refresh
|
||
- Auto-clears on tab close
|
||
- **Pros:** Persistence
|
||
- **Cons:** Limited size, string serialization
|
||
|
||
**Recommendation:** Use in-memory storage with sessionStorage backup
|
||
|
||
```javascript
|
||
class JointDataManager {
|
||
constructor() {
|
||
this.data = new Map();
|
||
this.loadFromSession();
|
||
}
|
||
|
||
save(shapeId, jointData) {
|
||
this.data.set(shapeId, jointData);
|
||
this.saveToSession();
|
||
}
|
||
|
||
saveToSession() {
|
||
const data = Object.fromEntries(this.data);
|
||
sessionStorage.setItem('jointData', JSON.stringify(data));
|
||
}
|
||
|
||
loadFromSession() {
|
||
const stored = sessionStorage.getItem('jointData');
|
||
if (stored) {
|
||
const data = JSON.parse(stored);
|
||
this.data = new Map(Object.entries(data));
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. Widget Positioning
|
||
|
||
**Option A: Fixed Position (Current)**
|
||
- Modal in center of screen
|
||
- **Pros:** Simple, consistent
|
||
- **Cons:** May cover important content
|
||
|
||
**Option B: Dynamic Positioning (Recommended)**
|
||
- Position near clicked shape
|
||
- Calculate based on shape coordinates
|
||
- **Pros:** Better UX, doesn't cover content
|
||
- **Cons:** More complex
|
||
|
||
**Recommendation:** Use dynamic positioning with fallback to center
|
||
|
||
```javascript
|
||
function calculateWidgetPosition(shape, canvas) {
|
||
const shapeBounds = shape.getBoundingRect();
|
||
const canvasOffset = canvas.getElement().getBoundingClientRect();
|
||
|
||
const x = canvasOffset.left + shapeBounds.left + shapeBounds.width;
|
||
const y = canvasOffset.top + shapeBounds.top;
|
||
|
||
// Check if fits on screen
|
||
const windowWidth = window.innerWidth;
|
||
const windowHeight = window.innerHeight;
|
||
const widgetWidth = 600; // Modal width
|
||
const widgetHeight = 500; // Estimated modal height
|
||
|
||
let finalX = x;
|
||
let finalY = y;
|
||
|
||
if (x + widgetWidth > windowWidth) {
|
||
finalX = x - widgetWidth - 20; // Position to left
|
||
}
|
||
|
||
if (y + widgetHeight > windowHeight) {
|
||
finalY = windowHeight - widgetHeight - 20;
|
||
}
|
||
|
||
return { x: finalX, y: finalY };
|
||
}
|
||
```
|
||
|
||
### 3. API Design
|
||
|
||
**RESTful Endpoints:**
|
||
```
|
||
POST /api/pdf-editor/joint-data - Save joint data
|
||
GET /api/pdf-editor/joint-data/{id} - Get joint data
|
||
PUT /api/pdf-editor/joint-data/{id} - Update joint data
|
||
DELETE /api/pdf-editor/joint-data/{id} - Delete joint data
|
||
GET /api/pdf-editor/qualified-welders - Get qualified welders
|
||
GET /api/pdf-editor/check-weldmap - Check existing weldmap data
|
||
```
|
||
|
||
**Request/Response Format:**
|
||
```json
|
||
// POST /api/pdf-editor/joint-data
|
||
{
|
||
"drawing_number": "CW-800-AH01JL-FA00.001",
|
||
"joints": [
|
||
{
|
||
"shape_id": "J-001",
|
||
"joint_no": "53A",
|
||
"type_of_joint": "F",
|
||
"welding_date": "2025-01-15",
|
||
"spool_no1": "SP01",
|
||
"spool_no2": "SP02",
|
||
// ... other fields
|
||
}
|
||
]
|
||
}
|
||
|
||
// Response
|
||
{
|
||
"success": true,
|
||
"message": "Joint data saved successfully",
|
||
"data": {
|
||
"saved_count": 1,
|
||
"joints": [...]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4. Database Transactions
|
||
|
||
**Best Practice:** Use database transactions for data integrity
|
||
|
||
```php
|
||
public function saveJointData(Request $request): JsonResponse
|
||
{
|
||
DB::beginTransaction();
|
||
|
||
try {
|
||
foreach ($request->joints as $jointData) {
|
||
WeldLog::updateOrCreate(
|
||
[
|
||
'iso_number' => $request->drawing_number,
|
||
'no_of_the_joint_as_per_as_built_survey' => $jointData['joint_no'],
|
||
],
|
||
[
|
||
// ... field mappings
|
||
]
|
||
);
|
||
}
|
||
|
||
DB::commit();
|
||
return response()->json(['success' => true]);
|
||
} catch (\Exception $e) {
|
||
DB::rollBack();
|
||
Log::error('Failed to save joint data', ['error' => $e->getMessage()]);
|
||
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 5. Welder Qualification Filtering
|
||
|
||
**Integration with Existing System:**
|
||
- Reuse `welder_1.php` autocomplete logic
|
||
- Filter by material compatibility (MaterialGroupMap)
|
||
- Filter by welding method
|
||
- Check expiry dates
|
||
- Filter by qualification status
|
||
|
||
**Implementation:**
|
||
```php
|
||
public function getQualifiedWelders(Request $request): JsonResponse
|
||
{
|
||
$request->validate([
|
||
'material_1' => 'required|string',
|
||
'material_2' => 'required|string',
|
||
'welding_method' => 'required|string',
|
||
'joint_type' => 'nullable|string',
|
||
]);
|
||
|
||
// Use existing welder assignment logic
|
||
$qualifiedWelders = $this->filterQualifiedWelders(
|
||
$request->material_1,
|
||
$request->material_2,
|
||
$request->welding_method
|
||
);
|
||
|
||
return response()->json([
|
||
'success' => true,
|
||
'data' => $qualifiedWelders
|
||
]);
|
||
}
|
||
```
|
||
|
||
### 6. Performance Optimization
|
||
|
||
**Client-Side:**
|
||
- Debounce API calls (300ms)
|
||
- Cache API responses
|
||
- Use virtual scrolling for large lists
|
||
- Lazy load widget modal
|
||
- Use requestAnimationFrame for animations
|
||
|
||
**Server-Side:**
|
||
- Use database indexes
|
||
- Implement query caching
|
||
- Use eager loading for relationships
|
||
- Implement pagination
|
||
- Use database transactions efficiently
|
||
|
||
### 7. Error Handling
|
||
|
||
**Client-Side:**
|
||
```javascript
|
||
async function saveJointData(jointData) {
|
||
try {
|
||
const response = await fetch('/api/pdf-editor/joint-data', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRF-TOKEN': csrfToken
|
||
},
|
||
body: JSON.stringify(jointData)
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (!result.success) {
|
||
throw new Error(result.message || 'Failed to save joint data');
|
||
}
|
||
|
||
return result;
|
||
} catch (error) {
|
||
console.error('Error saving joint data:', error);
|
||
Swal.fire('Error', error.message, 'error');
|
||
throw error;
|
||
}
|
||
}
|
||
```
|
||
|
||
**Server-Side:**
|
||
```php
|
||
try {
|
||
// ... operation
|
||
} catch (ValidationException $e) {
|
||
return response()->json([
|
||
'success' => false,
|
||
'message' => 'Validation failed',
|
||
'errors' => $e->errors()
|
||
], 422);
|
||
} catch (\Exception $e) {
|
||
Log::error('Joint data save failed', [
|
||
'error' => $e->getMessage(),
|
||
'trace' => $e->getTraceAsString()
|
||
]);
|
||
|
||
return response()->json([
|
||
'success' => false,
|
||
'message' => 'An error occurred while saving joint data'
|
||
], 500);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 Testing Strategy
|
||
|
||
### Unit Tests
|
||
- JointDataManager class methods
|
||
- API endpoint validation
|
||
- Database operations
|
||
- Data mapping functions
|
||
|
||
### Integration Tests
|
||
- Widget open/close flow
|
||
- Data save/load cycle
|
||
- API endpoint integration
|
||
- Database transaction rollback
|
||
|
||
### E2E Tests
|
||
- Complete joint creation flow
|
||
- Welder assignment flow
|
||
- Drawing generation from data
|
||
- Document Revision save
|
||
|
||
---
|
||
|
||
## 📝 Implementation Checklist
|
||
|
||
### Phase 1: Foundation
|
||
- [ ] Create JointDataManager class
|
||
- [ ] Enhance joint widget modal
|
||
- [ ] Add IC Log member selection
|
||
- [ ] Implement auto-fill logic
|
||
|
||
### Phase 2: Integration
|
||
- [ ] Add shape click handlers
|
||
- [ ] Implement widget positioning
|
||
- [ ] Connect widget to data manager
|
||
- [ ] Update shape labels
|
||
|
||
### Phase 3: Backend
|
||
- [ ] Enhance saveJointData endpoint
|
||
- [ ] Create getQualifiedWelders endpoint
|
||
- [ ] Implement Base Weldmap integration
|
||
- [ ] Implement Weldlog integration
|
||
|
||
### Phase 4: Two-Way Sync
|
||
- [ ] Create check-existing-weldmap endpoint
|
||
- [ ] Implement left panel activation
|
||
- [ ] Create drawing from data
|
||
- [ ] Handle welder display
|
||
|
||
### Phase 5: Document Revision
|
||
- [ ] Implement Spool Iso save
|
||
- [ ] Implement As-Build save
|
||
- [ ] Add versioning support
|
||
|
||
### Phase 6: Welder Filtering
|
||
- [ ] Integrate qualification system
|
||
- [ ] Implement material filtering
|
||
- [ ] Add expiry date checking
|
||
|
||
---
|
||
|
||
## 🚀 Next Steps
|
||
|
||
1. **Review and approve roadmap**
|
||
2. **Set up development branch:** `feature/pdf-editor-step3-joint-widget`
|
||
3. **Start with Phase 1:** Foundation & Data Structure
|
||
4. **Iterative development:** Test each phase before moving to next
|
||
5. **Code review:** After each phase completion
|
||
|
||
---
|
||
|
||
## 📖 References
|
||
|
||
- Existing Code:
|
||
- `app/Http/Controllers/Api/AnnotationController.php`
|
||
- `app/Http/Controllers/Api/PdfEditorLookupController.php`
|
||
- `resources/views/components/modals/joint-widget-modal.blade.php`
|
||
- `app/Http/Controllers/AutoCompleteType/welder-assignment/welder_1.php`
|
||
|
||
- Database Tables:
|
||
- `weld_logs` - Main joint and welder data
|
||
- `annotations` - PDF shape data
|
||
- `document_revisions` - PDF file storage
|
||
- `incoming_control` - IC Log member data
|
||
- `material_group_map` - Material compatibility
|
||
- `welder_tests` - Welder qualifications
|
||
|
||
---
|
||
|
||
**Document Version:** 1.0
|
||
**Last Updated:** 2025-01-XX
|
||
**Author:** Development Team
|
||
|