Snippets Collections
#merge sort

#the merge algorithm
def merge(L1, L2, L):
  i = 0
  j = 0
  while i+j < len(L):
    if j == len(L2) or (i < len(L1) and L1[i] < L2[j]):
       L[i+j] = L1[i]
       i += 1
    else:
       L[i+j] = L2[j]
       j += 1

#main function
def merge_sort(L):

  n = len(L)
  if n < 2:
     return # list is already sorted

  # divide
  mid = n // 2 #midpoint
  L1 = L[0:mid] # the first half
  L2 = L[mid:n] # the second half
 
  # conquer with recursion
  merge_sort(L1) # sort first sub-list
  merge_sort(L2) # sort second sub-list

  # merge result
  merge(L1, L2, L) 

#example
L = [7, 5, 1, 4, 2, 8, 0, 9, 3, 6]
print('Before: ', L)
merge_sort(L)
print('After: ', L)
def insertion_sort(lst):
   for i in range(1, len(lst)):
      j = i
      while (j > 0) and lst[j-1] > lst[j]:
         lst[j-1], lst[j] = lst[j], lst[j-1] #swap the elements
         j -=1

#sort a list
L = [5, 2, 9, 3, 6, 1, 0, 7, 4, 8]
insertion_sort(L)
print("The sorted list is: ", L)
#descending selection sort
def selection_sort(lst):
  for i in range(len(lst)):
    smallest = i

    for j in range(i + 1, len(lst)):
      if lst[j] > lst[smallest]:
        smallest = j

    lst[i], lst[smallest] = lst[smallest], lst[i] #swap the elements

#sort a list
L = [99, 9, 0, 2, 1, 0, 1, 100, -2, 8, 7, 4, 3, 2]
selection_sort(L)

print("The sorted list is: ", L)
def selection_sort(lst):
  for i in range(len(lst)):
    smallest = i

    for j in range(i + 1, len(lst)):
      if lst[j] < lst[smallest]:
        smallest = j

    lst[i], lst[smallest] = lst[smallest], lst[i] #swap the elements

#sort a list
L = [99, 9, 0, 2, 1, 0, 1, 100, -2, 8, 7, 4, 3, 2]
selection_sort(L)

print("The sorted list is: ", L)
#Optimized bubble sort
def bubble_sort(lst):

  swapped = True
  while swapped == True:
    swapped = False
    for j in range(len(lst)-1):  
      
      if(lst[j]>lst[j+1]):
        lst[j], lst[j + 1] = lst[j + 1], lst[j] #swap the elements
        swapped = True

#sort a list
L = [9, 0, 2, 1, 0, 1, 100, -2, 8, 7, 4, 3, 2]

bubble_sort(L)  
print("The sorted list is: ", L)
#import the random module
import random

#The list to shuffle
my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

#shuffle the list in-place
random.shuffle(my_list)

print(my_list)
#import the random module
import random

#The sequence to sample
my_seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

#get a sample of 4 elements
print(random.sample(my_seq, 4))
myset = {1, 3, 5, 7, 9, 11}

#remove an arbitrary element
print(myset.pop())
print(myset.pop())
print(myset.pop())
print(myset.pop())

print(myset)
#raises a KeyError if the element does not exist

myset = {0, 2, 3, 4, 6, 7, 8, 9}
myset.remove(3)
myset.remove(7)
myset.remove(9)

print(myset)
#unlike set.remove(), If the target element does not exist, set.discard method does not raise a KeyError, it returns None instead.

myset = {1, 3, 4, 5, 7, 8, 9}

#remove elements
myset.discard(4)
myset.discard(8)

print(myset)
myset = {'Python', 'Java', 'C++'}

#add elements to the set
myset.add('PHP')
myset.add('HTML')
myset.add('Javascript')

print(myset)
import functools

def power(a, b):
    return a ** b

square = functools.partial(power, b = 2)
cube = functools.partial(power, b = 3)

print(square(5))
print(cube(5))
#finally block always gets executed
#else block is only executed if no exception was raised

import math

try:
   print("Hello, World!")
   print(10/ 5)
   print(math.sqrt(-9))

except ValueError:
   print("a ValueError has occurred")

except IndexError:
    print("IndexError has occurred")

else:
    print("No Exception was raised.")
finally:
    print("This block always gets executed")
#The else block only gets executed if the try block terminates successfully i.e  no exception was raised inside the block.


import math

try:
   print("Hello, World!")
   print(10/ 2)
   print(math.sqrt(9))

except ValueError:
   print("a valu error has occurred")

except IndexError:
    print("IndexError has occurred")

else:
    print("No Exception was raised.")
import math

try:
   
   #This will raise a TypeError
   print( 3 + 'hello' )

   #This will raise a ValueError
   math.sqrt(-16)

   #This will raise a NameError
   print(a)
   
   #This will raise a zeroDivisionError
   print(10 / 0)

except NameError:
    print("A NameError occurred")

except ValueError: 
    print("A ValueError occurred")

except ZeroDivisionError:
    print("A ZeroDivisionError occurred")

except TypeError:
    print("A TypeError occurred")
try:
   
    print(1 / 0)

except ZeroDivisionError:
    print("You divided a number by 0.")
#import the ChainMap class
from collections import ChainMap

d1 = {'one': 1, 'two': 2, 'three': 3}
d2 = {'four': 4, 'five': 5, 'six': 6}
d3 = {'seven': 7, 'eight': 8, 'nine': 9}

chain = ChainMap(d1, d2, d3)

print(chain)
#a list of strings
languages = ['Python', 'Java']

#append an element
languages.append('PHP')
print(languages)

languages.append('C++')
print(languages)

languages.append('Javascript')
print(languages)
def add(a, b):
    print(f'{a} + {b} = {a + b}')

a = 10
b = 20
add(a, b)
#itertools.count()- creates an iterator which yields infinite sequence of integers from a starting point 

from itertools import count

seq = count(0, 2) #an infinite sequence of even numbers

print(next(seq))
print(next(seq))
print(next(seq))
print(next(seq))
print(next(seq))
#itertools.product() Generates the cartesian product of two iterables 

from itertools import product

data1 = [1, 2]
data2 = [10, 20]

result = product(data1, data2)

L = list(result) #turn the iterator into a list
print(L)
data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

def is_odd(num):
   return num % 2 == 1

odds = filter(is_odd, data)

print(*odds)
from itertools import repeat

#repeat a string 10 times
r = repeat('Spam', 10)
print(r)

for i in r:
    print(i)
SELECT SubscriberKey, EmailAddress, System_Language__c, Mailing_Country__c, First_Name__c, Cat_Campaign_Most_Recent__c, Business_Unit__c, System_Opt_in_for_eMail__c, DateAdded, PCCReg
FROM (
SELECT
DISTINCT i.SubscriberKey
	,i.EmailAddress
	,i.System_Language__c
	,i.Mailing_Country__c
	,i.First_Name__c
	,i.Cat_Campaign_Most_Recent__c
	,i.Business_Unit__c
	,i.System_Opt_in_for_eMail__c
	,i.DateAdded
	,i.PCCReg,
 
ROW_NUMBER() OVER(PARTITION BY c.ID ORDER BY inta.LastModifiedDate DESC) as RowNum
 
FROM ent.Interaction__c_Salesforce inta
JOIN ent.Contact_Salesforce_1 c ON LOWER(c.Email) = LOWER(inta.Email__c)
JOIN [Proposed_Retail_TA_News_2024_INCLUDE] i ON LOWER(inta.Email__c) = LOWER(i.EmailAddress)
LEFT JOIN ps_an_en_us_s190010_Retail_TA_Segment_sendable_2021 mst ON LOWER(inta.Email__c) = LOWER(mst.EmailAddress)
WHERE 1 = 1
    AND i.SYSTEM_OPT_IN_FOR_EMAIL__C = '1'
    AND NOT EXISTS (
        SELECT NULL
        FROM [Proposed_Retail_TA_News_2024_EXCLUDE] ex
        WHERE 1 = 1
            AND i.SubscriberKey = ex.SubscriberKey
    ))t2
 
WHERE RowNum = 1
RenameColumns = Table.TransformColumnNames("Removed Other Columns", each Text.Proper(Text.Replace(Text.Replace(_, "crb3f_", ""), "_", " ")))
//TS
import { Component } from '@angular/core';
import { Chart } from 'chart.js';
@Component({
  selector: 'app-bar-line',
  templateUrl: './bar-line.component.html',
  styleUrls: ['./bar-line.component.scss']
})
export class BarLineComponent {
  ngOnInit(): void {
    this.createChart();
  }
  public chart: any;
  createChart(){
    this.chart = new Chart("bar-line", {
      type: 'line',
      data: {
        labels: ['Shirt', 'Jacket', 'Men Tops', 'Men Pants', 
                 'Swimwear', 'Shoes', 'Sleepwear', 'Men Accessories'],
        datasets:[
          {
            label:"2022",
            data: ['446','551','462','158','171','553','566','231']
          },
          {
            type:'bar',
            label:"2023",
            data: ['623','431','525','306','100','369','417','420']
          }
        ]
      }
    });
  }
}
//HTML
<div class="chart-container">
    <h2>Product Sales</h2>
    <canvas id="bar-line">{{ chart }}</canvas>
</div>
//TS
import { Component } from '@angular/core';
import {Chart, ChartDataset, ChartType} from 'chart.js';

@Component({
  selector: 'app-pie-chart',
  templateUrl: './pie-chart.component.html',
  styleUrls: ['./pie-chart.component.scss']
})
export class PieChartComponent {
  ngOnInit(): void {
    this.createChart();
  }
  public chart: any;
  createChart(){
    this.chart = new Chart("pie-chart", {
      type: 'pie',
      data: {
        labels: ['Shirt', 'Jacket', 'Men Tops', 'Men Pants', 
                 'Swimwear', 'Shoes', 'Sleepwear', 'Men Accessories'],
        datasets:[
          {
            label:"2022",
            data: ['446','551','462','158','171','553','566','231']
          },
          {
            label:"2023",
            data: ['623','431','525','306','100','369','417','420']
          }
        ]
      }
    });
  }
}
//HTML
<div class="chart-container">
    <h2>Product Sales</h2>
    <canvas id="pie-chart">{{ chart }}</canvas>
</div>
//TS
import { Component } from '@angular/core';
import {Chart, ChartDataset, ChartType} from 'chart.js';



@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
  
})
export class HomeComponent {
  ngOnInit(): void {
    this.createChart();
  }
  public chart: any;
  createChart(){
    this.chart = new Chart("barChart", {
      type: 'bar',
      data: {
        labels: ['Shirt', 'Jacket', 'Men Tops', 'Men Pants', 
                 'Swimwear', 'Shoes', 'Sleepwear', 'Men Accessories'],
        datasets:[
          {
            label:"2022",
            data: ['446','551','462','158','171','553','566','231'],
            backgroundColor: 'blue'
          },
          {
            label:"2023",
            data: ['623','431','525','306','100','369','417','420'],
            backgroundColor: 'red'
          }
        ]
      }
    });
  }
}
//HTML
<div class="chart-container">
    <h2>Product Sales</h2>
    <canvas id="barChart">{{ chart }}</canvas>
</div>
//{ Driver Code Starts
#include <bits/stdc++.h>
using namespace std;

// } Driver Code Ends
//User function template for C++
class Solution{
public:
    
    int onesinrow(vector<vector<int>> &arr, int i){
        int lower = lower_bound(arr[i].begin(), arr[i].end(), 1) - arr[i].begin();
        return arr[i].size() - lower;
    }

    int rowWithMax1s(vector<vector<int>> &arr, int n, int m) {
        int ans = 0;
        int ind = -1;
        for(int i = 0; i < n; i++){
            int ones = onesinrow(arr, i);
            if(ones > ans){
                ans = ones;
                ind = i;
            }
        }
        return ind;
    }
};

//{ Driver Code Starts.
int main() {
    int t;
    cin >> t;
    while (t--) {
        int n, m;
        cin >> n >> m;
        vector< vector<int> > arr(n,vector<int>(m));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cin>>arr[i][j];
            }
        }
        Solution ob;
        auto ans = ob.rowWithMax1s(arr, n, m);
        cout << ans << "\n";
    }
    return 0;
}

// } Driver Code Ends
<nav class="navbar navbar-expand-sm bg-success navbar-dark">
  <a class="navbar-brand" href="#">Reporting</a>
  <button class="navbar-toggler"> data-target="#mynav">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="mynav">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item">
        <a class="nav-1link" routerLink="home">Home</a>
      </li>
      <li class="nav-item">
        <a class="nav-1link" routerLink="pie-chart">Pie Chart</a>
      </li>
      <li class="nav-item">
        <a class="nav-1link" routerLink="bar-line">Bar Line Chart</a>
      </li>
    </ul>
  </div>
</nav>
#include <bits/stdc++.h>
using namespace std;

class Solution{   
public:
    // Function to count elements <= mid_val using binary search
    int countSmallerThanOrEqualToMid(vector<int> &row, int mid_val) {
        int low = 0, high = row.size() - 1;
        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (row[mid] <= mid_val) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return low;  // The number of elements <= mid_val
    }

    int median(vector<vector<int>> &matrix, int R, int C){
        int min_val = INT_MAX;
        int max_val = INT_MIN;

        // Find the minimum and maximum element in the matrix
        for (int i = 0; i < R; ++i) {
            if (matrix[i][0] < min_val) min_val = matrix[i][0];
            if (matrix[i][C - 1] > max_val) max_val = matrix[i][C - 1];
        }

        int desired_count = (R * C + 1) / 2;
        
        while (min_val < max_val) {
            int mid_val = min_val + (max_val - min_val) / 2;
            int count = 0;

            // Count elements <= mid_val using binary search
            for (int i = 0; i < R; ++i) {
                count += countSmallerThanOrEqualToMid(matrix[i], mid_val);
            }

            // Adjust search range based on the count
            if (count < desired_count) {
                min_val = mid_val + 1;
            } else {
                max_val = mid_val;
            }
        }
        
        return min_val;
    }
};

int main() {
    int t;
    cin >> t;
    while (t--) {
        int r, c;
        cin >> r >> c;
        vector<vector<int>> matrix(r, vector<int>(c));
        for (int i = 0; i < r; ++i)
            for (int j = 0; j < c; ++j)
                cin >> matrix[i][j];
        Solution obj;
        int ans = obj.median(matrix, r, c);
        cout << ans << "\n";        
    }
    return 0;
}
const getSelectValue = (callback) => {
  const options = getElement("#city-select");

  options.addEventListener("change", function (e) {
    const value = e.target.value;
    // pass the value into the callback function we can use later
    callback(value); // this value needs to be passed into the function where we are using the getSelectValue function ie  getSelectValue(value)
  });
};




// app function
const init = () => {
  // populate the DOM with the cities data on load
  const selectDOM = getElement("#city-select");
  populateDOM(cities, selectDOM);

  let selectedCity = ""; // this gets updated with the function below

  // need to run the callback here
  // get the value and assign it to a variable outside the function
  getSelectValue((value) => {
    selectedCity = value; // Assign the value to selectedCity
    //  // Log the selected city
    if (selectedCity !== "") {
      const container = getElement(".container h3");
      container.textContent = selectedCity;
    }
  });
};

window.addEventListener("DOMContentLoaded", init);

let score = 85;

let grade = (score >= 90) ? 'A' : 
            (score >= 80) ? 'B' : 
            (score >= 70) ? 'C' : 
            (score >= 60) ? 'D' : 'F';

console.log(`The grade is ${grade}`);
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { RegisterUser } from '../shared/register-user';
import { LoginUser } from '../shared/login-user';
import { User } from '../shared/user';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class BackendService {

  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  };

  constructor(private http: HttpClient) {}
  endPoint: string = "http://localhost:5240/api/";

  RegisterUser(registerUser: RegisterUser) {
    return this.http.post(`${this.endPoint}Authentication/Register`, registerUser, this.httpOptions);
  }

  LoginUser(loginUser: LoginUser): Observable<User> {
    return this.http.post<User>(`${this.endPoint}Authentication/Login`, loginUser, this.httpOptions);
  }
}
//TS
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { Router, RouterLink } from '@angular/router';
import { BackendService } from '../services/backend.service';
import { MaterialModule } from '../shared/material.module';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatSnackBar } from '@angular/material/snack-bar';

@Component({
  selector: 'app-login',
  standalone: true,
  imports: [
    MaterialModule,
    ReactiveFormsModule,
    RouterLink,
    CommonModule,
    HttpClientModule, 
    FlexLayoutModule
],
  templateUrl: './login.component.html',
  styleUrl: './login.component.scss'
})
export class LoginComponent {
  loginFormGroup: FormGroup;
  isLoading: boolean = false;

  constructor(
    private router: Router,
    private backendService: BackendService,
    private fb: FormBuilder,
    private snackBar: MatSnackBar
  ) {
    this.loginFormGroup = this.fb.group({
      email: ['', [Validators.required, Validators.email]],
      password: ['', [Validators.required, Validators.minLength(8), Validators.maxLength(16)]]
    });
  }

  ngOnInit(): void {}

  LoginUser() {
    if (this.loginFormGroup.valid) {
      this.isLoading = true;

      this.backendService.LoginUser(this.loginFormGroup.value).subscribe({
        next: (result) => {
          localStorage.setItem('User', JSON.stringify(result));
          this.loginFormGroup.reset();
          this.router.navigateByUrl('product-listing');
          this.snackBar.open('Login successful', 'X', { duration: 2000 });
          this.isLoading = false;
        },
        error: (err) => {
          let errorMessage = 'Login failed. Please try again.';
          if (err.status === 401) {
            errorMessage = 'Invalid email or password.';
          } else if (err.status === 500) {
            errorMessage = 'Internal server error. Please contact support.';
          }
          this.snackBar.open(errorMessage, 'X', { duration: 3000 });
          this.isLoading = false;
        }
      });
    } else {
      this.snackBar.open('Please fill out the form correctly.', 'X', { duration: 3000 });
    }
  }
}
//Memo
export class LoginComponent implements OnInit {

  loginFormGroup: FormGroup = this.fb.group({
    emailaddress: ['', [Validators.required, Validators.email]],
    password: ['', Validators.required],
  })

  isLoading:boolean = false

  constructor(private router: Router, private apiService: APIService, private fb: FormBuilder, private snackBar: MatSnackBar) { }

  ngOnInit(): void {}

  async LoginUser(){
    if(this.loginFormGroup.valid)
    {
      this.isLoading = true

      await this.apiService.LoginUser(this.loginFormGroup.value).subscribe(result => {
        localStorage.setItem('User', JSON.stringify(result))
        this.loginFormGroup.reset();
        this.router.navigateByUrl('productListing');
      })
    }
  }
}
//Logout
ngOnInit(): void {
    this.isLoggedIn = localStorage.getItem('User') ? true : false;
  }
logout(): void {
    localStorage.removeItem('User');
    this.router.navigateByUrl('login');
    this.snackBar.open('You have been successfully logged out.', 'X', {duration: 3000});
  }
//OR
logout(){
    if(localStorage.getItem('User'))
    {
      localStorage.removeItem('User')
      this.router.navigateByUrl('login');
    }
  }
//HTML
<div class="login-wrapper" fxLayout="row" fxLayoutAlign="center center">
  <mat-card class="box" *ngIf="!isLoading">
    <mat-card-header>
      <mat-card-title>Log in</mat-card-title>
    </mat-card-header>
    <form class="form" [formGroup]="loginFormGroup" (ngSubmit)="LoginUser()">
      <mat-card-content>
        <mat-form-field class="full-width">
          <mat-label>Email Address</mat-label>
          <input matInput placeholder="e.g., user@example.com" formControlName="email">
          <mat-error *ngIf="loginFormGroup.controls['email'].hasError('required')">Email is required</mat-error>
          <mat-error *ngIf="loginFormGroup.controls['email'].hasError('email')">Enter a valid email</mat-error>
        </mat-form-field>
        <mat-form-field class="full-width">
          <mat-label>Password</mat-label>
          <input type="password" matInput placeholder="e.g., 8-16 characters" formControlName="password">
          <mat-error *ngIf="loginFormGroup.controls['password'].hasError('required')">Password is required</mat-error>
          <mat-error *ngIf="loginFormGroup.controls['password'].hasError('minlength')">Minimum 8 characters required</mat-error>
          <mat-error *ngIf="loginFormGroup.controls['password'].hasError('maxlength')">Maximum 16 characters allowed</mat-error>
        </mat-form-field>
      </mat-card-content>
      <mat-card-actions>
        <button mat-stroked-button color="primary" class="btn-block" type="submit">Log in</button>
      </mat-card-actions>
      <div style="text-align: center;">Don't have an account? <a [routerLink]="['../register']">Register</a></div>
    </form>
  </mat-card>
  <mat-progress-spinner mode="indeterminate" *ngIf="isLoading"></mat-progress-spinner>
</div>
//TS
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { Router, RouterLink } from '@angular/router';
import { BackendService } from '../services/backend.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { MaterialModule } from '../shared/material.module';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { FlexLayoutModule } from '@angular/flex-layout';

@Component({
  selector: 'app-register',
  standalone: true,
  imports: [
    MaterialModule,
    ReactiveFormsModule,
    RouterLink,
    CommonModule,
    HttpClientModule, 
    FlexLayoutModule
  ],
  templateUrl: './register.component.html',
  styleUrl: './register.component.scss'
})
export class RegisterComponent{
  registerFormGroup: FormGroup;

  constructor(private router: Router, private backendService: BackendService, private fb: FormBuilder, private snackBar: MatSnackBar) { 
    this.registerFormGroup = this.fb.group({
      email: ['', [Validators.required, Validators.email]],
      password: ['', [Validators.required, Validators.minLength(8), Validators.maxLength(16)]]
    });
  }

  ngOnInit(): void {
  }

  RegisterUser() {
    if (this.registerFormGroup.valid) {
      this.backendService.RegisterUser(this.registerFormGroup.value).subscribe({
        next: () => {
          this.registerFormGroup.reset();
          this.router.navigate(['/login']).then(navigated => {
            if (navigated) {
              this.snackBar.open('Registered successfully', 'X', { duration: 2000 });
            }
          });
        },
        error: (err) => {
          let errorMessage = 'Registration failed. Please try again.';
          if (err.status === 403) {
            errorMessage = 'Account already exists.';
          } else if (err.status === 500) {
            errorMessage = 'Internal server error. Please contact support.';
          }
          this.snackBar.open(errorMessage, 'X', { duration: 3000 });
        }
      });
    } else {
      this.snackBar.open('Please fill out the form correctly.', 'X', { duration: 3000 });
    }
  }
  

  cancel() {
    this.registerFormGroup.reset();
    this.router.navigate(['/login']);
  }
}

//HTML
<div class="login-wrapper" fxLayout="row" fxLayoutAlign="center center">
  <mat-card class="box">
    <mat-card-header>
      <mat-card-title>Register</mat-card-title>
    </mat-card-header>
    <form class="form" [formGroup]="registerFormGroup" (ngSubmit)="RegisterUser()">
      <mat-card-content>
        <mat-form-field class="full-width">
          <mat-label>Email Address</mat-label>
          <input matInput placeholder="e.g., user@example.com" formControlName="email">
          <mat-error *ngIf="registerFormGroup.controls['email'].hasError('required')">Email is required</mat-error>
          <mat-error *ngIf="registerFormGroup.controls['email'].hasError('email')">Enter a valid email</mat-error>
        </mat-form-field>
        <mat-form-field class="full-width">
          <mat-label>Password</mat-label>
          <input type="password" matInput placeholder="Enter between 8 to 16 characters" formControlName="password">
          <mat-error *ngIf="registerFormGroup.controls['password'].hasError('required')">Password is required</mat-error>
          <mat-error *ngIf="registerFormGroup.controls['password'].hasError('minlength')">Minimum 8 characters required</mat-error>
          <mat-error *ngIf="registerFormGroup.controls['password'].hasError('maxlength')">Maximum 16 characters allowed</mat-error>
        </mat-form-field>
      </mat-card-content>
      <mat-card-actions>
        <button mat-stroked-button color="primary" class="btn-block" type="submit">Register</button>
        <button mat-stroked-button color="warn" class="btn-block" type="button" (click)="cancel()">Cancel</button>
      </mat-card-actions>
    </form>
  </mat-card>
</div>
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Server=DESKTOP-9QI4G7U\\SQLEXPRESS;Database=INF354Assignment3;Trusted_Connection=True;MultipleActiveResultSets=True"
  },
  "Tokens": {
    "Key": "y+VRv[&)0XhxJ<sk=yUpW{yE5CH@xh",
    "Issuer": "localhost",
    "Audience": "localhost"
  }
}
using Assignment3_Backend.Factory;
using Assignment3_Backend.Models;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddCors(options => options.AddDefaultPolicy(
    include =>
    {
        include.AllowAnyHeader();
        include.AllowAnyMethod();
        include.AllowAnyOrigin();
    }));

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

//For identity
builder.Services.AddIdentity<AppUser, IdentityRole>(options =>
{
    options.Password.RequireUppercase = false;
    options.Password.RequireLowercase = false;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequireDigit = true;
    options.User.RequireUniqueEmail = true;
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();

//Adding JWT Bearer
builder.Services.AddAuthentication()
                .AddCookie()
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters()
                    {
                        ValidIssuer = builder.Configuration["Tokens:Issuer"],
                        ValidAudience = builder.Configuration["Tokens:Audience"],
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Tokens:Key"]))
                    };
                });

// File upload functionality
builder.Services.Configure<FormOptions>(o =>
{
    o.ValueLengthLimit = int.MaxValue;
    o.MultipartBodyLengthLimit = int.MaxValue;
    o.MemoryBufferThreshold = int.MaxValue;
});

builder.Services.AddScoped<IUserClaimsPrincipalFactory<AppUser>, AppUserClaimsPrincipalFactory>();

builder.Services.Configure<DataProtectionTokenProviderOptions>(options => options.TokenLifespan = TimeSpan.FromHours(3));

//For Entity Framework
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddScoped<IRepository, Repository>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseCors();
app.UseAuthentication();
app.UseAuthorization();


app.MapControllers();

app.Run();
[Route("api/[controller]")]
[ApiController]
public class AuthenticationController : ControllerBase
{
    private readonly UserManager<AppUser> _userManager;
    private readonly IRepository _repository;
    private readonly IUserClaimsPrincipalFactory<AppUser> _claimsPrincipalFactory;
    private readonly IConfiguration _configuration;

    public AuthenticationController(UserManager<AppUser> userManager, IUserClaimsPrincipalFactory<AppUser> claimsPrincipalFactory, IConfiguration configuration, IRepository repository)
    {
        _userManager = userManager;
        _claimsPrincipalFactory = claimsPrincipalFactory;
        _configuration = configuration;
        _repository = repository;
    }

    [HttpPost]
    [Route("RegisterUser")]
    public async Task<IActionResult>RegisterUser(UserViewModel uvm)
    {
        var user = await _userManager.FindByNameAsync(uvm.username);
        if (user == null)
        {
            try
            {
                string phoneNumberPattern = @"^0\d{9}$";
                bool isValidPhoneNumber = Regex.IsMatch(uvm.phonenumber, phoneNumberPattern);
                if (!isValidPhoneNumber) return BadRequest("Please enter a valid 10-digit phone number");
                user = new AppUser
                {
                    Id= Guid.NewGuid().ToString(),
                    UserName= uvm.username,
                    Email=  uvm.emailaddress,
                    PhoneNumber= uvm.phonenumber
                };
                var result= await _userManager.CreateAsync(user, uvm.password);
                if (result.Errors.Count() > 0)
                {
                    StringBuilder errorlist = new StringBuilder("These registration errors need to be resolved");
                    foreach (var error in result.Errors)
                    {
                        errorlist.Append($"{error.Code}: {error.Description}");
                    }
                    return BadRequest($"{errorlist}");
                }
            }
            catch (Exception ex)
            {
                return StatusCode(StatusCodes.Status500InternalServerError, $"Error occured{ex.Message}");
            }
        }
        else
        {
            return Conflict($"The username '{uvm.username}' already exists. Please use a different username");
        }
        return Ok($"Your account '{uvm.username}' was created successfully. You may proceed with logging in");
    }
}
//Password and Email
builder.Services.AddIdentity<AppUser, IdentityRole>(options =>
{
    options.User.RequireUniqueEmail = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequiredLength = 12;
    options.Password.RequireDigit = true;
    options.Password.RequireUppercase = true;
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
[Route("api/[controller]")]
[ApiController]
public class AuthenticationController : ControllerBase
{
    private readonly UserManager<AppUser> _userManager;
    private readonly IUserClaimsPrincipalFactory<AppUser> _claimsFactory;
    private readonly IRepository _repository;
    private readonly IConfiguration _configuration;

    public AuthenticationController(UserManager<AppUser> userManager, IUserClaimsPrincipalFactory<AppUser> claimsPrincipalFactory, IRepository repository, IConfiguration configuration)
    {
        _repository = repository;
        _userManager = userManager;
        _claimsFactory = claimsPrincipalFactory;
        _configuration = configuration;
    }

    [HttpPost]
    [Route("Register")]
    public async Task<IActionResult> Register(UserViewModel userViewModel)
    {
        var user = await _userManager.FindByIdAsync(userViewModel.email);

        if (user == null)
        {
            user = new AppUser
            {
                Id = Guid.NewGuid().ToString(),
                UserName = userViewModel.email,
                Email = userViewModel.email
            };

            var result = await _userManager.CreateAsync(user, userViewModel.password);

            if (result.Errors.Count() > 0) return StatusCode(StatusCodes.Status500InternalServerError, "Internal Server Error. Please contact support.");
        }
        else
        {
            return Forbid("Account already exists.");
        }

        return Ok();
    }

    [HttpPost]
    [Route("Login")]
    public async Task<ActionResult> Login(UserViewModel uvm)
    {
        var user = await _userManager.FindByNameAsync(uvm.email);

        if (user != null && await _userManager.CheckPasswordAsync(user, uvm.password))
        {
            try
            {
                var userPrincipal = await _claimsFactory.CreateAsync(user);
                return GenerateJWTToken(user);
            }
            catch (Exception)
            {
                return StatusCode(StatusCodes.Status500InternalServerError, "Internal Server Error. Please contact support.");
            }
        }
        else
        {
            return NotFound("Does not exist");
        }
    }

    [HttpGet]
    private ActionResult GenerateJWTToken(AppUser user)
    {
        // Create JWT Token
        var userClaims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Sub, user.Email),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName)
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Tokens:Key"]));
        var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var token = new JwtSecurityToken(
            _configuration["Tokens:Issuer"],
            _configuration["Tokens:Audience"],
            userClaims  ,
            signingCredentials: credentials,
            expires: DateTime.UtcNow.AddHours(3)
        );

        return Created("", new
        {
            token = new JwtSecurityTokenHandler().WriteToken(token),
            user = user.UserName
        });
    }
}
@ -0,0 +1,159 @@
import {
  ButtonContent,
  DestructiveButton,
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
  Icon,
  If,
  Input,
  Toaster,
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "ui";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import type * as z from "zod";
import React, { useEffect, useState } from "react";
import { toast } from "sonner";
import wretch from "wretch";
import {
  fieldsNameHelper,
  formSchema,
  numberFields,
  toTitleCase,
} from "./regularVesselInfoForm";

interface AddRegularVesselFormProps {
  fields: string[];
  vesselId?: string;
  imo?: string;
  returnIdentifier: (identifier: any) => void;
}

export const AddRegularVesselForm = ({
  fields,
  vesselId,
  imo,
  returnIdentifier,
}: AddRegularVesselFormProps) => {
  const excludeFields: string[] = ["id"];
  const disabledFields: string[] = ["vessel_id", "imo"];

  const [identifier, setIdentifier] = useState<string>(vesselId || imo || "");

  fields = fields?.sort().filter((item) => !excludeFields.includes(item));

  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      vessel_id: vesselId,
      imo: imo,
    },
  });

  async function onSubmit(values: z.infer<typeof formSchema>) {
    const addVessel: VesselInfo = Object.entries(values).reduce(
      (acc: VesselInfo, [key, value]) => {
        const vesselInfoKey: string = fieldsNameHelper[key].name;
        acc[vesselInfoKey] = (value || "").toString().toLowerCase();
        return acc;
      },
      {},
    );

    try {
      const response = await wretch("/api/form/regularVessel")
        .post(addVessel)
        .res();

      if (response.ok) {
        toast.success("Success!", {
          description: "Vessel details inserted.",
        });
        returnIdentifier({ vessel_id: values.vessel_id, imo: values.imo });
      } else {
        toast.error("Error submitting form");
      }
    } catch (error) {
      toast.error("Something went wrong", {
        description: (error as PostgrestError | null)?.message,
      });
    }
  }

  const reset = form.reset;

  useEffect(() => {
    reset({}, { keepValues: false });

    reset(
      {
        vessel_id: vesselId,
        imo: imo,
      },
      { keepValues: false },
    );
  }, [reset]);

  return (
    <div className={"mt-4"}>
      <Form {...form}>
        <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
          {Object.keys(formSchema.shape).map((key, index) => (
            <>
              <If condition={fields?.includes(fieldsNameHelper[key].name)}>
                <FormField
                  key={key + index}
                  control={form.control}
                  name={key as any}
                  render={({ field }) => (
                    <FormItem className={"flex flex-row items-center"}>
                      <FormLabel className={"w-64 text-lg font-light"}>
                        {toTitleCase(fieldsNameHelper[key].name)}
                      </FormLabel>
                      <div className={"mr-2"}>
                        <TooltipProvider>
                          <Tooltip>
                            <TooltipTrigger className="text-black hover:text-black/50 dark:text-white dark:hover:text-white/50">
                              <Icon name="unknown" style="h-5 w-5" />
                            </TooltipTrigger>
                            <TooltipContent>
                              <p>{fieldsNameHelper[key].description}</p>
                            </TooltipContent>
                          </Tooltip>
                        </TooltipProvider>
                      </div>
                      <FormControl className={"w-full"}>
                        <Input
                          className={"text-md font-light"}
                          required={false}
                          {...field}
                          type={numberFields.includes(key) ? "number" : "text"}
                          value={field.value ?? ""}
                          disabled={disabledFields.includes(key)}
                        />
                      </FormControl>
                      <FormMessage />
                    </FormItem>
                  )}
                />
              </If>
            </>
          ))}
          <div className="flex flex-row justify-end">
            <DestructiveButton type="submit" className="mt-4">
              <ButtonContent>Add vessel</ButtonContent>
            </DestructiveButton>
          </div>
          <Toaster />
        </form>
      </Form>
    </div>
  );
};
@ -0,0 +1,396 @@
import {
  ButtonContent,
  DestructiveButton,
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
  Icon,
  If,
  Input,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
  Toaster,
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "ui";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import * as z from "zod";
import React, { useEffect, useState } from "react";
import { toast } from "sonner";
import wretch from "wretch";

export interface VesselInfo {
  [key: string]: string | undefined;
}

interface RegularVesselFormProps {
  vesselInfo: VesselInfo;
  vesselId?: string;
  imo?: string;
}

export const formSchema = z.object({
  imo: z.string().optional(),
  cargoType: z.string().optional(),
  cargoSubType: z.string().optional(),
  mmsi: z.string().optional(),
  vesselName: z.string().optional(),
  yearOfBuild: z.string().optional(),
  flag: z.string().optional(),
  dwt: z.string().optional(),
  maximumDraft: z.string().optional(),
  geared: z.string().optional(),
  gearDetails: z.string().optional(),
});

type FieldsNameHelper = {
  [key: string]: { name: string; description: string };
};

export const fieldsNameHelper: FieldsNameHelper = {
  imo: {
    name: "IMO",
    description: "International Maritime Organization identifier",
  },
  cargoType: {
    name: "Cargo Type",
    description: "The type of cargo the vessel carries",
  },
  cargoSubType: {
    name: "Cargo Sub Type",
    description: "The subtype of cargo the vessel carries",
  },
  mmsi: { name: "MMSI", description: "Maritime Mobile Service Identity" },
  vesselName: { name: "Vessel Name", description: "The name of the vessel" },
  yearOfBuild: {
    name: "Year of Build",
    description: "The year the vessel was built",
  },
  flag: { name: "Flag", description: "The flag country code" },
  dwt: { name: "DWT", description: "Dead Weight Tonnage" },
  maximumDraft: {
    name: "Maximum Draft",
    description:
      "The deepest point of the vessel below the waterline when fully loaded",
  },
  geared: {
    name: "Geared",
    description: "Indicates if the vessel is geared (yes or no)",
  },
  gearDetails: {
    name: "Gear Details",
    description: "Details about the vessel's gear",
  },
};

export const numberFields: string[] = [
  "dwt",
  "yearOfBuild",
  "maximumDraft",
  "mmsi",
  "imo",
];

export const uppercaseFields: string[] = ["imo", "mmsi"];

export function toTitleCase(str: string): string {
  if (uppercaseFields.includes(str)) {
    return str.toUpperCase().replace("_", " ");
  } else {
    str = str.replace("_", " ");
    return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
  }
}

export const RegularVesselInfoForm = ({
  vesselInfo,
  vesselId,
  imo,
}: RegularVesselFormProps) => {
  const disabledFields: string[] = ["vesselId", "imo"];
  const [selectedType, setSelectedType] = useState<string | null>(
    vesselInfo?.cargoType ?? null,
  );

  const defaultFieldsValues = Object.fromEntries(
    Object.keys(fieldsNameHelper).map((key) => [
      key,
      vesselInfo ? vesselInfo[fieldsNameHelper[key].name as string] ?? "" : "",
    ]),
  );

  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: defaultFieldsValues,
  });

  useEffect(() => {
    if (vesselInfo) {
      form.reset(defaultFieldsValues);
    }
  }, [vesselInfo]);

  async function onSubmit(values: z.infer<typeof formSchema>) {
    const updatedVesselInfo: VesselInfo = Object.entries(values).reduce(
      (acc: VesselInfo, [key, value]) => {
        const vesselInfoKey: string = fieldsNameHelper[key].name;
        acc[vesselInfoKey] = (value || "").toString().toLowerCase();
        return acc;
      },
      {},
    );

    try {
      const response = await wretch("/api/form/regularVessel")
        .post(updatedVesselInfo)
        .res();
      if (response.ok) {
        await wretch(`/api/form/regularVessel?vessel_id=${vesselId}&imo=${imo}`)
          .get()
          .json();
        toast.success("Success!", {
          description: "Vessel details updated.",
        });
      } else {
        toast.error("Error submitting form");
      }
    } catch (error) {
      toast.error("Something went wrong", {
        description: (error as any)?.message,
      });
    }
  }

  return (
    <div className="mt-6 flex w-full flex-col gap-2 p-2 sm:w-1/2">
      <Form {...form}>
        <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
          {Object.keys(formSchema.shape).map((key, index) => (
            <React.Fragment key={key}>
              <If
                condition={Object.keys(vesselInfo || {}).includes(
                  fieldsNameHelper[key].name,
                )}
              >
                <If
                  condition={
                    key !== "type" && key !== "subType" && key !== "buildYear"
                  }
                >
                  <FormField
                    key={key}
                    control={form.control}
                    name={key as any}
                    render={({ field }) => (
                      <FormItem className={"flex flex-row items-center"}>
                        <FormLabel className={"w-64 text-lg font-light"}>
                          {toTitleCase(fieldsNameHelper[key].name)}
                        </FormLabel>
                        <div className={"mr-2"}>
                          <TooltipProvider>
                            <Tooltip>
                              <TooltipTrigger className="text-black hover:text-black/50 dark:text-white dark:hover:text-white/50">
                                <Icon name="unknown" style="h-5 w-5" />
                              </TooltipTrigger>
                              <TooltipContent>
                                <p>{fieldsNameHelper[key].description}</p>
                              </TooltipContent>
                            </Tooltip>
                          </TooltipProvider>
                        </div>
                        <FormControl className={"w-full"}>
                          <Input
                            {...field}
                            className={"text-md font-light"}
                            type={
                              numberFields.includes(key) ? "number" : "text"
                            }
                            value={field.value ?? ""}
                            disabled={disabledFields.includes(key)}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </If>
                <If condition={key === "type"}>
                  <FormField
                    control={form.control}
                    name="type"
                    render={({ field }) => (
                      <FormItem className={"flex flex-row items-center"}>
                        <FormLabel className={"w-64 text-lg font-light"}>
                          Type
                        </FormLabel>
                        <div className={"mr-2"}>
                          <TooltipProvider>
                            <Tooltip>
                              <TooltipTrigger className="text-black hover:text-black/50 dark:text-white dark:hover:text-white/50">
                                <Icon name="unknown" style="h-5 w-5" />
                              </TooltipTrigger>
                              <TooltipContent>
                                <p>{fieldsNameHelper[key].description}</p>
                              </TooltipContent>
                            </Tooltip>
                          </TooltipProvider>
                        </div>
                        <Select
                          onValueChange={(value: any) => {
                            field.onChange(value);
                            setSelectedType(value);
                          }}
                          value={field.value ?? ""}
                        >
                          <FormControl className={"text-md w-full font-light"}>
                            <SelectTrigger>
                              <SelectValue placeholder="Select a type" />
                            </SelectTrigger>
                          </FormControl>
                          <SelectContent>
                            <SelectItem value={"cargo vessel"}>
                              Cargo Vessel
                            </SelectItem>
                            <SelectItem value={"tanker"}>Tanker</SelectItem>
                            <SelectItem value={"passenger vessel"}>
                              Passenger Vessel
                            </SelectItem>
                            <SelectItem value={"other"}>Other</SelectItem>
                          </SelectContent>
                        </Select>
                      </FormItem>
                    )}
                  />
                </If>
                <If condition={key === "subType"}>
                  <FormField
                    control={form.control}
                    name="subType"
                    render={({ field }) => (
                      <FormItem className={"flex flex-row items-center"}>
                        <FormLabel className={"w-64 text-lg font-light"}>
                          Sub type
                        </FormLabel>
                        <div className={"mr-2"}>
                          <TooltipProvider>
                            <Tooltip>
                              <TooltipTrigger className="text-black hover:text-black/50 dark:text-white dark:hover:text-white/50">
                                <Icon name="unknown" style="h-5 w-5" />
                              </TooltipTrigger>
                              <TooltipContent>
                                <p>{fieldsNameHelper[key].description}</p>
                              </TooltipContent>
                            </Tooltip>
                          </TooltipProvider>
                        </div>
                        <Select
                          onValueChange={field.onChange}
                          value={field.value ?? ""}
                        >
                          <FormControl className={"text-md w-full font-light"}>
                            <SelectTrigger>
                              <SelectValue placeholder="Select a sub type" />
                            </SelectTrigger>
                          </FormControl>
                          {selectedType && selectedType === "cargo vessel" && (
                            <SelectContent>
                              <SelectItem value={"bulk carrier"}>
                                Bulk Carrier
                              </SelectItem>
                              <SelectItem value={"container ship"}>
                                Container Ship
                              </SelectItem>
                              <SelectItem value={"general cargo ship"}>
                                General Cargo Ship
                              </SelectItem>
                            </SelectContent>
                          )}
                          {selectedType && selectedType === "tanker" && (
                            <SelectContent>
                              <SelectItem value={"oil tanker"}>
                                Oil Tanker
                              </SelectItem>
                              <SelectItem value={"chemical tanker"}>
                                Chemical Tanker
                              </SelectItem>
                              <SelectItem value={"gas carrier"}>
                                Gas Carrier
                              </SelectItem>
                            </SelectContent>
                          )}
                          {selectedType &&
                            selectedType === "passenger vessel" && (
                              <SelectContent>
                                <SelectItem value={"cruise ship"}>
                                  Cruise Ship
                                </SelectItem>
                                <SelectItem value={"ferry"}>Ferry</SelectItem>
                              </SelectContent>
                            )}
                        </Select>
                      </FormItem>
                    )}
                  />
                </If>
                <If condition={key === "buildYear"}>
                  <FormField
                    control={form.control}
                    name="buildYear"
                    render={({ field }) => (
                      <FormItem className={"flex flex-row items-center"}>
                        <FormLabel className={"w-64 text-lg font-light"}>
                          Build year
                        </FormLabel>
                        <div className={"mr-2"}>
                          <TooltipProvider>
                            <Tooltip>
                              <TooltipTrigger className="text-black hover:text-black/50 dark:text-white dark:hover:text-white/50">
                                <Icon name="unknown" style="h-5 w-5" />
                              </TooltipTrigger>
                              <TooltipContent>
                                <p>{fieldsNameHelper[key].description}</p>
                              </TooltipContent>
                            </Tooltip>
                          </TooltipProvider>
                        </div>
                        <FormControl className={"w-full"}>
                          <Input
                            {...field}
                            className={"text-md font-light"}
                            type="number"
                            min={1900}
                            max={2100}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </If>
              </If>
            </React.Fragment>
          ))}
          <If
            condition={vesselInfo && Object.keys(formSchema.shape).length > 0}
          >
            <div className="flex flex-row justify-end">
              <DestructiveButton type="submit" className="mt-4">
                <ButtonContent>Update</ButtonContent>
              </DestructiveButton>
            </div>
          </If>
          <Toaster />
        </form>
      </Form>
    </div>
  );
};
@ -0,0 +1,121 @@
// regularVesselRds.ts

import {rdsConnection} from "@/lib/aws";
import type {Vessel, VesselDetails} from "@/types";

// Fetch regular vessel information by vessel_id or imo
export async function getRegularVessel(identifier: {
  vessel_id?: string;
  imo?: string;
}) {
  const { vessel_id, imo } = identifier;
  const query = vessel_id
    ? `SELECT v.vessel_id, v.dwt, v.imo, v.flag, v.mmsi, v.vessel_name, v.cargo_type, v.cargo_sub_type, v.year_of_build, v.maximum_draft, d.geared, d.gear_details
       FROM spotship_vessel AS v
       LEFT JOIN spotship_vesseldetails AS d ON v.vessel_id = d.vessel_id
       WHERE v.vessel_id = ? LIMIT 1`
    : `SELECT v.vessel_id, v.dwt, v.imo, v.flag, v.mmsi, v.vessel_name, v.cargo_type, v.cargo_sub_type, v.year_of_build, v.maximum_draft, d.geared, d.gear_details
       FROM spotship_vessel AS v
       LEFT JOIN spotship_vesseldetails AS d ON v.vessel_id = d.vessel_id
       WHERE v.imo = ? LIMIT 1`;

  const value = vessel_id || imo;

  return await new Promise<{ vessel: Vessel; details: VesselDetails }[]>(
    (resolve, reject) => {
      rdsConnection.query(
        query,
        [value],
        (
          error: unknown,
          elements: { vessel: Vessel; details: VesselDetails }[],
        ) => {
          if (error) {
            return reject(error);
          }
          return resolve(elements);
        },
      );
    },
  );
}

// Insert new regular vessel information
export async function insertRegularVessel(data: any) {
  const { vessel, details } = data;
  return await new Promise<void>((resolve, reject) => {
    rdsConnection.query(
      `INSERT INTO spotship_vessel (vessel_id, dwt, imo, flag, mmsi, vessel_name, cargo_type, cargo_sub_type, year_of_build, maximum_draft)
       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
      [
        vessel.vessel_id,
        vessel.dwt,
        vessel.imo,
        vessel.flag,
        vessel.mmsi,
        vessel.vessel_name,
        vessel.cargo_type,
        vessel.cargo_sub_type,
        vessel.year_of_build,
        vessel.maximum_draft,
      ],
      (error: unknown) => {
        if (error) {
          console.error("Insert spotship_vessel error: ", error); // Log error
          return reject(error);
        }
        rdsConnection.query(
          `INSERT INTO spotship_vesseldetails (vessel_id, geared, gear_details) VALUES (?, ?, ?)`,
          [vessel.vessel_id, details.geared, details.gear_details],
          (error: unknown) => {
            if (error) {
              console.error("Insert spotship_vesseldetails error: ", error); // Log error
              return reject(error);
            }
            return resolve();
          },
        );
      },
    );
  });
}

// Update existing regular vessel information
export async function updateRegularVessel(data: any) {
  const { vessel, details } = data;
  return await new Promise<void>((resolve, reject) => {
    rdsConnection.query(
      `UPDATE spotship_vessel SET dwt = ?, imo = ?, flag = ?, mmsi = ?, vessel_name = ?, cargo_type = ?, cargo_sub_type = ?, year_of_build = ?, maximum_draft = ?
       WHERE vessel_id = ?`,
      [
        vessel.dwt,
        vessel.imo,
        vessel.flag,
        vessel.mmsi,
        vessel.vessel_name,
        vessel.cargo_type,
        vessel.cargo_sub_type,
        vessel.year_of_build,
        vessel.maximum_draft,
        vessel.vessel_id,
      ],
      (error: unknown) => {
        if (error) {
          console.error("Update spotship_vessel error: ", error); // Log error
          return reject(error);
        }
        rdsConnection.query(
          `UPDATE spotship_vesseldetails SET geared = ?, gear_details = ? WHERE vessel_id = ?`,
          [details.geared, details.gear_details, vessel.vessel_id],
          (error: unknown) => {
            if (error) {
              console.error("Update spotship_vesseldetails error: ", error); // Log error
              return reject(error);
            }
            return resolve();
          },
        );
      },
    );
  });
}
star

Tue Jun 18 2024 03:24:52 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/data-structures/implement-merge-sort-in-python/

@pynerds #python

star

Tue Jun 18 2024 03:23:53 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/data-structures/implement-insertion-sort-in-python/

@pynerds #python

star

Tue Jun 18 2024 03:23:20 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/data-structures/implement-selection-sort-in-python/

@pynerds #python

star

Tue Jun 18 2024 03:22:36 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/data-structures/implement-selection-sort-in-python/

@pynerds

star

Tue Jun 18 2024 03:21:14 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/data-structures/implement-bubble-sort-algorithm-in-python/

@pynerds #python

star

Tue Jun 18 2024 03:18:11 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/python-collections-module/

@pynerds #python

star

Tue Jun 18 2024 03:13:58 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/python-collections-deque/

@pynerds #python

star

Tue Jun 18 2024 03:06:00 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/python-random-shuffle-function/

@pynerds #python

star

Tue Jun 18 2024 03:04:26 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/python-random-sample-function/

@pynerds #python

star

Tue Jun 18 2024 03:03:04 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/set-pop-method-in-python/

@pynerds #python

star

Tue Jun 18 2024 03:02:04 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/set-remove-method-in-python/

@pynerds

star

Tue Jun 18 2024 02:57:51 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/set-discard-method-in-python/

@pynerds #python

star

Tue Jun 18 2024 02:56:17 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/set-methods-in-python/

@pynerds

star

Tue Jun 18 2024 02:54:06 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/set-add-method-in-python/

@pynerds #python

star

Tue Jun 18 2024 02:53:02 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/partial-functions-in-python/

@pynerds #python

star

Tue Jun 18 2024 02:48:31 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/exception-handling-in-python/

@pynerds #python

star

Tue Jun 18 2024 02:44:46 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/exception-handling-in-python/

@pynerds #python

star

Tue Jun 18 2024 02:40:57 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/exception-handling-in-python/

@pynerds #python

star

Tue Jun 18 2024 02:37:17 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/exception-handling-in-python/

@pynerds #python

star

Tue Jun 18 2024 02:36:11 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/exception-handling-in-python/

@pynerds #python

star

Tue Jun 18 2024 02:33:06 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/compiler/

@pynerds

star

Tue Jun 18 2024 02:31:18 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/python-collections-chainmap/

@pynerds

star

Tue Jun 18 2024 02:29:03 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/python-add-items-to-a-list/

@pynerds #python

star

Tue Jun 18 2024 02:27:25 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/compiler/

@pynerds #python

star

Tue Jun 18 2024 02:25:51 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/python-itertools-count/

@pynerds #python

star

Tue Jun 18 2024 02:23:54 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/python-itertools-product/

@pynerds

star

Tue Jun 18 2024 02:12:48 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/python-itertools-filterfalse/

@pynerds #python

star

Tue Jun 18 2024 02:07:54 GMT+0000 (Coordinated Universal Time) https://www.pynerds.com/python-itertools-repeat/

@pynerds #python

star

Mon Jun 17 2024 19:30:56 GMT+0000 (Coordinated Universal Time)

@shirnunn

star

Mon Jun 17 2024 17:55:55 GMT+0000 (Coordinated Universal Time)

@bdusenberry

star

Mon Jun 17 2024 17:22:43 GMT+0000 (Coordinated Universal Time) https://www.facebook.com/checkpoint/?next

@gangaa

star

Mon Jun 17 2024 13:31:13 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 13:26:04 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 13:03:44 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 13:00:01 GMT+0000 (Coordinated Universal Time)

@Xeno_SSY #c++

star

Mon Jun 17 2024 12:45:27 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 12:30:16 GMT+0000 (Coordinated Universal Time)

@Xeno_SSY

star

Mon Jun 17 2024 11:39:55 GMT+0000 (Coordinated Universal Time)

@davidmchale #callback

star

Mon Jun 17 2024 11:06:30 GMT+0000 (Coordinated Universal Time)

@davidmchale #loop #index #array

star

Mon Jun 17 2024 10:05:47 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 09:35:03 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 09:19:07 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 09:14:49 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 09:01:45 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 08:48:51 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 08:45:49 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 08:41:47 GMT+0000 (Coordinated Universal Time)

@iamkatmakhafola

star

Mon Jun 17 2024 07:18:57 GMT+0000 (Coordinated Universal Time)

@rafal_rydz

star

Mon Jun 17 2024 07:18:31 GMT+0000 (Coordinated Universal Time)

@rafal_rydz

star

Mon Jun 17 2024 07:17:21 GMT+0000 (Coordinated Universal Time)

@rafal_rydz

Save snippets that work with our extensions

Available in the Chrome Web Store Get Firefox Add-on Get VS Code extension