article

Wednesday, June 9, 2021

SwiftUI fetch image from URL

SwiftUI fetch image from URL
 
//
//  ContentView.swift
//  Test
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    var body: some View {
        Image(systemName: "person.fill")
            .data(url: URL(string: "https://freepngimg.com/thumb/one_piece/23231-5-one-piece-chibi-image-thumb.png")!)
            .scaleEffect()
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

extension Image {
    func data(url:URL) -> Self {
        if let data = try? Data(contentsOf: url) {
            return Image(uiImage: UIImage(data: data)!)
                .resizable()
        }
        return self
            .resizable()
    }
}

Sunday, June 6, 2021

Display Loading Image when AJAX call is in Progress using Python Flask PostgreSQL

Display Loading Image when AJAX call is in Progress using Python Flask PostgreSQL

install psycopg2 https://pypi.org/project/psycopg2/
Psycopg is the most popular PostgreSQL database adapter for the Python programming language.
(venv) PS C:\flaskmyproject> pip install psycopg2

CREATE TABLE posts (
id serial PRIMARY KEY,
title VARCHAR ( 100 ) NOT NULL,
content TEXT NOT NULL,
link VARCHAR ( 100 ) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);


INSERT INTO
    posts(title, content, link, created_at)
VALUES
('What is AngularJS', 'AngularJS is a JavaScript MVC framework  developed by Google that lets you build well structured, easily testable,  declarative and maintainable front-end applications which provides solutions to  standard infrastructure concerns.', 'link-5', '2021-03-20 16:00:00'),
('What is MongoDB', 'It is a quick tutorial on MongoDB and how you can install it on your Windows OS. We will also learn some basic commands in MongoDB for example, creating and dropping a Database, Creation of a collection and some more operations related to the collection.', 'link-6', '2021-03-21 16:00:00'),
('Python Flask Load content Dynamically in Bootstrap Modal with Jquery AJAX and Mysqldb', 'Python Flask Load content Dynamically in Bootstrap Modal with Jquery AJAX and Mysqldb', 'link-6', '2021-03-20 16:00:00'),
('AutoComplete Textbox with Image using jQuery Ajax PHP Mysql and JqueryUI', 'AutoComplete Textbox with Image using jQuery Ajax PHP Mysql and JqueryUI', 'link-7', '2021-03-14 16:00:00'),
('PHP Mysql Registration Form Validation using jqBootstrapValidation with Jquery Ajax', 'PHP Mysql Registration Form Validation using jqBootstrapValidation with Jquery Ajax', 'link-8', '2021-03-20 16:00:00'),
('Python Flask Registration Form Validation using jqBootstrapValidation with Jquery Ajax and Mysql', 'Python Flask Registration Form Validation using jqBootstrapValidation with Jquery Ajax and Mysql', 'link-9', '2021-03-19 16:00:00'),
('Displaying Popups data on mouse hover using Jquery Ajax and PHP Mysql database', 'Displaying Popups data on mouse hover using Jquery Ajax and PHP Mysql database', 'link-10', '2021-03-15 16:00:00'),
('Displaying Popups data on mouse hover using Jquery Ajax and Python Flask Mysql database', 'Displaying Popups data on mouse hover using Jquery Ajax and Python Flask Mysql database', 'link-11', '2021-03-14 16:00:00');

app.py
 
#app.py
from flask import Flask, request, render_template, jsonify, json
import psycopg2 #pip install psycopg2 
import psycopg2.extras
   
app = Flask(__name__)
   
app.secret_key = "cairocoders-ednalan"
   
DB_HOST = "localhost"
DB_NAME = "sampledb"
DB_USER = "postgres"
DB_PASS = "admin"
   
conn = psycopg2.connect(dbname=DB_NAME, user=DB_USER, password=DB_PASS, host=DB_HOST)

@app.route('/')
def home():
    return render_template('index.html')
 
@app.route("/fetchdeta",methods=["POST","GET"])
def fetchdeta():
    cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    if request.method == 'POST':
        search = request.form['search']
        print(search)
        query = "SELECT * from posts WHERE title LIKE '%{}%'".format(search,)
        cursor.execute(query)
        postslist = cursor.fetchall() 
        cursor.close()
    return jsonify({'htmlresponse': render_template('response.html',postslist=postslist)})
             
if __name__ == "__main__":
    app.run()
templates.index.html
//templates.index.html
<html>
 <head>
  <title>Display Loading Image when AJAX call is in Progress using Python Flask PostgreSQL</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />        
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
 </head>
 <body>
  <div class="container">
  <div class="row">
   <h3 align="center">Display Loading Image when AJAX call is in Progress using Python Flask PostgreSQL</h3>
    Search : 
    <input type='text' id='search' class="form-control" style="width:40%;"><br/>
    <input type='button' id='but_search' value='Search' class="btn btn-default"><br/>
    <!-- Image loader -->
    <div id='loader' style='display: none;'>
      <img src='/static/img/loader.gif'> <b>Loading..</b>
    </div>
    <br/>
    <!-- Image loader -->
    <div class='response'></div>
   </div>
  </div>
<script type='text/javascript'>
 
$(document).ready(function(){
  
 $("#but_search").click(function(){
  var search = $('#search').val();
 
  $.ajax({
   url: '/fetchdeta',
   type: 'post',
   data: {search:search},
   beforeSend: function(){
    // Show image container
    $("#loader").show();
   },
   success: function(response){
    $('.response').empty();
    $('.response').append(response.htmlresponse);
   },
   complete:function(data){
    // Hide image container
    $("#loader").hide();
   }
  });
  
 });
});
</script>
<style>
.post{
    width: 97%;
    min-height: 200px;
    padding: 5px;
    border: 1px solid gray;
    margin-bottom: 15px;
}
.post h1{
    letter-spacing: 1px;
    font-weight: normal;
    font-family: sans-serif;
}
.post p{
    letter-spacing: 1px;
    text-overflow: ellipsis;
    line-height: 25px;
}
</style>
 </body>
</html>
templates/response.html
//templates/response.html
{% for row in postslist %}
<div class="post" id="post_{{row.id}}">
<h1>{{row.title}}</h1>
<p>{{row.content}}</p>
<a href="{{row.link}}" class="more" target="_blank">More</a>
</div>
{% endfor %}

Friday, June 4, 2021

Filter Records using jQuery UI slider with Jquery Ajax and Python Flask PostgreSQL

Filter Records using jQuery UI slider with Jquery Ajax and Python Flask PostgreSQL

install psycopg2 https://pypi.org/project/psycopg2/
Psycopg is the most popular PostgreSQL database adapter for the Python programming language.
(venv) PS C:\flaskmyproject> pip install psycopg2

CREATE TABLE employee (
id serial PRIMARY KEY,
name VARCHAR ( 100 ) NOT NULL,
position VARCHAR ( 100 ) NOT NULL,
office VARCHAR ( 100 ) NOT NULL,
age INT NOT NULL,
salary INT NOT NULL,
photo VARCHAR ( 150 ) NOT NULL,
);


INSERT INTO
    employee(name, position, office, age, salary, photo)
VALUES
('Tiger Wood', 'Accountant', 'Tokyo', 36, 5689, '01.jpg'),
('Mark Oto Ednalan', 'Chief Executive Officer (CEO)', 'London', 56, 5648, '02.jpg'),
('Jacob thompson', 'Junior Technical Author', 'San Francisco', 23, 5689, '03.jpg'),
('cylde Ednalan', 'Software Engineer', 'Olongapo', 23, 54654, '04.jpg'),
('Rhona Davidson', 'Software Engineer', 'San Francisco', 26, 5465, '05.jpg'),
('Quinn Flynn', 'Integration Specialist', 'New York', 53, 56465, '06.jpg'),
('Tiger Nixon', 'Software Engineer', 'London', 45, 456, '07.jpg'),
('Airi Satou', 'Pre-Sales Support', 'New York', 25, 4568, '08.jpg'),
('Angelica Ramos', 'Sales Assistant', 'New York', 45, 456, '09.jpg'),
('Ashton updated', 'Senior Javascript Developer', 'Olongapo', 45, 54565, '01.jpg'),
('Bradley Greer', 'Regional Director', 'San Francisco', 27, 5485, '02.jpg'),
('Brenden Wagner', 'Javascript Developer', 'San Francisco', 38, 65468, '03.jpg'),
('Brielle Williamson', 'Personnel Lead', 'Olongapo', 56, 354685, '04.jpg'),
('Bruno Nash', 'Customer Support', 'New York', 36, 65465, '05.jpg'),
('cairocoders', 'Sales Assistant', 'Sydney', 45, 56465, '06.jpg'),
('Zorita Serrano', 'Support Engineer', 'San Francisco', 38, 6548, '07.jpg'),
('Zenaida Frank', 'Chief Operating Officer (COO)', 'San Francisco', 39, 545, '08.jpg'),
('Sakura Yamamoto', 'Support Engineer', 'Tokyo', 48, 5468, '05.jpg'),
('Serge Baldwin', 'Data Coordinator', 'Singapore', 85, 5646, '05.jpg'),
('Shad Decker', 'Regional Director', 'Tokyo', 45, 4545, '05.jpg');

JqueryUI Slider https://jqueryui.com/slider/
app.py
 
#app.py
from flask import Flask, request, render_template, jsonify, json
import psycopg2 #pip install psycopg2 
import psycopg2.extras
   
app = Flask(__name__)
   
app.secret_key = "cairocoders-ednalan"
   
DB_HOST = "localhost"
DB_NAME = "sampledb"
DB_USER = "postgres"
DB_PASS = "admin"
   
conn = psycopg2.connect(dbname=DB_NAME, user=DB_USER, password=DB_PASS, host=DB_HOST)

@app.route('/')
def home():
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        cursor.execute("SELECT * from employee order by name asc")
        employeelist = cursor.fetchall()
        return render_template('index.html',employeelist=employeelist)
    except Exception as e:
        print(e)
    finally:
        cursor.close() 
 
@app.route("/fetchdeta",methods=["POST","GET"])
def fetchdeta():
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        if request.method == 'POST':
            min = request.form['min']
            max = request.form['max']
            cursor.execute("SELECT * from employee WHERE salary>=(%s) AND salary<=(%s)", [min,max,])
            employeelist = cursor.fetchall()
            return jsonify({'htmlresponse': render_template('response.html',employeelist=employeelist)})
    except Exception as e:
        print(e)
    finally:
        cursor.close() 
 
if __name__ == "__main__":
    app.run()
templates/index.html
//templates/index.html
<!doctype html>
<html>
<head>
<title>Filter Records using jQuery UI slider with Jquery Ajax and Python Flask PostgreSQL</title>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script type='text/javascript'>
        $(document).ready(function(){
 
            // Initializing slider
            $( "#slider" ).slider({
                range: true,
                min: 100,
                max: 360000,
                values: [ 100, 360000 ],
                slide: function( event, ui ) {
                    // Get values
                    var min = ui.values[0];
                    var max = ui.values[1];
                    $('#range').text(min+' - ' + max);
 
                    // AJAX request
                    $.ajax({
                        url: '/fetchdeta',
                        type: 'post',
                        data: {min:min,max:max},
                        success: function(response){
 
                            // Updating table data
                            $('#emp_table tr:not(:first)').remove();
                            $('#emp_table').append(response.htmlresponse);    
                        }      
                    });
                }
            });
        });
        </script>
    </head>
    <body >
        <div class="container" >
        <div class="row" style="padding:50px;">
            <p><h1>Filter Records using jQuery UI slider with Jquery Ajax and Python Flask PostgreSQL</h1></p>
            <!-- slider --> 
            <div id="slider"></div><br/>
            Range: <span id='range'></span>
 
            <table id='emp_table' class="alternate" width='100%'>
                <tr>
                    <th>Name</th>
                    <th>Position</th>
                    <th>Office</th>
                    <th>Salary</th>
                    </tr>
                    {% for row in employeelist %}  
                    <tr>
                      <td>{{row.name}}</td>
                      <td>{{row.position}}</td>
                      <td>{{row.office}}</td>
                      <td>{{row.salary}}</td>
                    </tr>
                    {% endfor %} 
            </table>
        </div>
        </div>
<style>
.alternate tr:nth-child(2n) {
  background-color: silver;
}
.alternate tr {
  background-color: white;
}
.alternate tr td {padding: 8px;}
.alternate tr:nth-child(2n):hover, .alternate tr:hover {
  background-color: grey;
}
</style>  
</body>
</html>
templates/response.html
//templates/response.html
{% for row in employeelist %}
<tr>
    <td>{{row.name}}</td>
    <td>{{row.position}}</td>
    <td>{{row.office}}</td>
    <td>{{row.salary}}</td>
</tr>
{% endfor %} 

Thursday, June 3, 2021

SwiftUI Contact and Details Using List and Navigation View

SwiftUI Contact and Details Using List and Navigation View

ContentView.swift
 
//
//  ContentView.swift
//  Test
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            List(contacts) { contact in
                NavigationLink(destination: DetailView(contact: contact)) {
                    ContactRow(contact: contact)
                }
            }
            .navigationBarTitle("Contacts")
        }
        .environment(\.colorScheme, .light)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct ContactRow: View {
    
    let contact: Contact
    
    var body: some View {
        HStack {
            Image(contact.imageName)
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width: 60, height: 60)
                .clipped()
                .cornerRadius(50)
            VStack(alignment: .leading) {
                Text(contact.name)
                    .font(.system(size: 21, weight: .medium, design: .default))
                Text(contact.phone)
            }
        }
    }
}
Contact.swift
 
//
//  Contact.swift
//  Test
//
//  Created by Cairocoders
//

import Foundation

struct Contact: Identifiable {
    let imageName: String
    let name: String
    let phone: String
    let email: String
    let office: String
    let position: String
    let age: String
    let startdate: String
    let salary: Int
    let id = UUID()
}

let contacts = [
    Contact(imageName: "photo1", name: "Airi Satou", phone: "+0123-4567896", email: "airisatou@gmail.com", office: "Tokyo", position: "Accountant", age: "25", startdate: "2008/11/28", salary: 89560),
    Contact(imageName: "photo2", name: "Angelica Ramos", phone: "+1(698)-1881047", email: "engelicaramos@gmail.com.com", office: "London", position: "Chief Executive Officer (CEO)", age: "45", startdate: "2009/10/09", salary: 58568),
    Contact(imageName: "photo3", name: "Ashton Cox", phone: "+1(234)-3442899", email: "astoncox@gmail.com", office: "San Francisco", position: "Junior Technical Author", age: "56",startdate: "2008/11/28", salary: 1560),
    Contact(imageName: "photo4", name: "Bradley Greer", phone: "+1(765)-7448466", email: "bradlyfresn@gmail.com", office: "London", position: "Software Engineer", age: "26", startdate: "2008/11/28", salary: 9960),
    Contact(imageName: "photo5", name: "Brenden Wagner", phone: "+1(213)-5115553", email: "brdndanwgner@gmail.com", office: "San Francisco", position: "Software Engineer", age: "26", startdate: "2008/11/28", salary: 8860),
    Contact(imageName: "photo6", name: "Brielle Williamson", phone: "+1(453)-0663954", email: "brillewilson@gmail.com", office: "New York", position: "Software Engineer", age: "56", startdate: "2008/11/28", salary: 8760)
]
DetailView.swift
 
//
//  DetailView.swift
//  Test
//
//  Created by Cairocoders
//

import SwiftUI

struct DetailView: View {
    
    let contact: Contact
    
    var body: some View {
        VStack {
            Image(contact.imageName)
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width: 150, height: 150)
                .clipped()
                .cornerRadius(150)
                .shadow(radius: 3)
            Text(contact.name)
                .font(.title)
                .fontWeight(.medium)
            Form {
                Section {
                    HStack {
                        Text("Phone")
                        Spacer()
                        Text(contact.phone)
                            .foregroundColor(.gray)
                            .font(.callout)
                            .frame(alignment: .leading)
                    }
                    HStack {
                        Text("Email")
                        Spacer()
                        Text(contact.email)
                            .foregroundColor(.gray)
                            .font(.callout)
                            .frame(alignment: .leading)
                    }
                    HStack {
                        Text("Office")
                        Spacer()
                        Text(contact.office)
                            .foregroundColor(.gray)
                            .font(.callout)
                            .frame(alignment: .leading)
                            
                    }
                    HStack {
                        Text("Position")
                        Spacer()
                        Text(contact.position)
                            .foregroundColor(.gray)
                            .font(.callout)
                            .frame(alignment: .leading)
                            
                    }
                    HStack {
                        Text("Age")
                        Spacer()
                        Text(contact.age)
                            .foregroundColor(.gray)
                            .font(.callout)
                            .frame(alignment: .leading)
                            
                    }
                    HStack {
                        Text("Start Date")
                        Spacer()
                        Text(contact.startdate)
                            .foregroundColor(.gray)
                            .font(.callout)
                            .frame(alignment: .leading)
                            
                    }
                    HStack {
                        Text("Salary")
                        Spacer()
                        Text("$\(contact.salary)")
                            .foregroundColor(.gray)
                            .font(.callout)
                            .frame(alignment: .leading)
                            
                    }
                }
                Section {
                    Button(action: {
                        print("Send a message")
                    }) {
                        Text("Send a message")
                    }
                    Button(action: {
                        print("Call")
                    }) {
                        Text("Call")
                    }
                }
            }
        }
        .environment(\.colorScheme, .light)
    }
}

struct DetailView_Previews: PreviewProvider {
    static var previews: some View {
        DetailView(contact: contacts[0])
            .padding(.top, 60)
    }
}

Wednesday, June 2, 2021

SwiftUI Firestore CRUD Create, Read, Update and Delete

SwiftUI Firestore CRUD Create, Read, Update and Delete

Movie list screen is the homepage of the application it shows a list of all the movie records
Tap list item display details
tapping add plus button dialog form display add new records tap done button to add new movie
cancel button to dismiss dialog
tapping edit button to edit dialog form then save or Delete record

Swift packages https://github.com/firebase/firebase-ios-sdk

ContentView.swift
 
//
//  ContentView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    
    @StateObject var viewModel = MoviesViewModel() //MovieViewModel.swift
    @State var presentAddMovieSheet = false
    
    
    private var addButton: some View {
      Button(action: { self.presentAddMovieSheet.toggle() }) {
        Image(systemName: "plus")
      }
    }
    
    private func movieRowView(movie: Movie) -> some View {
       NavigationLink(destination: MovieDetailsView(movie: movie)) { //MovieDetailsView.swift
         VStack(alignment: .leading) {
           Text(movie.title)
             .font(.headline)
           //Text(movie.description)
           //  .font(.subheadline)
            Text(movie.year)
             .font(.subheadline)
         }
       }
    }
    
    var body: some View {
      NavigationView {
        List {
          ForEach (viewModel.movies) { movie in
            movieRowView(movie: movie)
          }
          .onDelete() { indexSet in
            //viewModel.removeMovies(atOffsets: indexSet)
            viewModel.removeMovies(atOffsets: indexSet)
          }
        }
        .navigationBarTitle("Movie")
        .navigationBarItems(trailing: addButton)
        .onAppear() {
          print("MoviesListView appears. Subscribing to data updates.")
          self.viewModel.subscribe()
        }
        .sheet(isPresented: self.$presentAddMovieSheet) {
          MovieEditView() //MovieEditView.swift
        }
        
      }// End Navigation
    }// End Body
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Models/Movie.swift
 
//
//  Movie.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import Foundation
import Foundation
import FirebaseFirestoreSwift

struct Movie: Identifiable, Codable {
  @DocumentID var id: String?
  var title: String
  var description: String
  var year: String
  
  enum CodingKeys: String, CodingKey {
    case id
    case title
    case description
    case year
  }
}
DevSwiftUIApp.swift
 
//
//  DevSwiftUIApp.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import Firebase

@main
struct DevSwiftUIApp: App {
    
    init() {
    FirebaseApp.configure()
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
ViewModels/MoviesViewModel.swift
 
//
//  MoviesViewModel.swift
//  DevSwiftUI
//
//  Created by Cairocoders on 6/3/21.
//

import Foundation
import Combine
import FirebaseFirestore

class MoviesViewModel: ObservableObject {
  @Published var movies = [Movie]()
  
  private var db = Firestore.firestore()
  private var listenerRegistration: ListenerRegistration?
  
  deinit {
    unsubscribe()
  }
  
  func unsubscribe() {
    if listenerRegistration != nil {
      listenerRegistration?.remove()
      listenerRegistration = nil
    }
  }
  
  func subscribe() {
    if listenerRegistration == nil {
      listenerRegistration = db.collection("movielist").addSnapshotListener { (querySnapshot, error) in
        guard let documents = querySnapshot?.documents else {
          print("No documents")
          return
        }
        
        self.movies = documents.compactMap { queryDocumentSnapshot in
          try? queryDocumentSnapshot.data(as: Movie.self)
        }
      }
    }
  }
  
  func removeMovies(atOffsets indexSet: IndexSet) {
    let movies = indexSet.lazy.map { self.movies[$0] }
    movies.forEach { movie in
      if let documentId = movie.id {
        db.collection("movielist").document(documentId).delete { error in
          if let error = error {
            print("Unable to remove document: \(error.localizedDescription)")
          }
        }
      }
    }
  }

  
}
ViewModels/MovieViewModel.swift
 
//
//  MovieViewModel.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import Foundation
import Combine
import FirebaseFirestore

class MovieViewModel: ObservableObject {
  
  @Published var movie: Movie
  @Published var modified = false
  
  private var cancellables = Set<anycancellable>()
  
  init(movie: Movie = Movie(title: "", description: "", year: "")) {
    self.movie = movie
    
    self.$movie
      .dropFirst()
      .sink { [weak self] movie in
        self?.modified = true
      }
      .store(in: &self.cancellables)
  }
  
  // Firestore
  
  private var db = Firestore.firestore()
  
  private func addMovie(_ movie: Movie) {
    do {
      let _ = try db.collection("movielist").addDocument(from: movie)
    }
    catch {
      print(error)
    }
  }
  
  private func updateMovie(_ movie: Movie) {
    if let documentId = movie.id {
      do {
        try db.collection("movielist").document(documentId).setData(from: movie)
      }
      catch {
        print(error)
      }
    }
  }
  
  private func updateOrAddMovie() {
    if let _ = movie.id {
      self.updateMovie(self.movie)
    }
    else {
      addMovie(movie)
    }
  }
  
  private func removeMovie() {
    if let documentId = movie.id {
      db.collection("movielist").document(documentId).delete { error in
        if let error = error {
          print(error.localizedDescription)
        }
      }
    }
  }
  
  // UI handlers
  
  func handleDoneTapped() {
    self.updateOrAddMovie()
  }
  
  func handleDeleteTapped() {
    self.removeMovie()
  }
  
}
View/MovieDetailsView.swift
 
//
//  MovieDetailsView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI

struct MovieDetailsView: View {
    @Environment(\.presentationMode) var presentationMode
    @State var presentEditMovieSheet = false
    
    var movie: Movie
    
    private func editButton(action: @escaping () -> Void) -> some View {
      Button(action: { action() }) {
        Text("Edit")
      }
    }
    
    var body: some View {
      Form {
        Section(header: Text("Movie")) {
          Text(movie.title)
          Text(movie.description)
            
        }
        
        Section(header: Text("Year")) {
            Text(movie.year)
        }
      }
      .navigationBarTitle(movie.title)
      .navigationBarItems(trailing: editButton {
        self.presentEditMovieSheet.toggle()
      })
      .onAppear() {
        print("MovieDetailsView.onAppear() for \(self.movie.title)")
      }
      .onDisappear() {
        print("MovieDetailsView.onDisappear()")
      }
      .sheet(isPresented: self.$presentEditMovieSheet) {
        MovieEditView(viewModel: MovieViewModel(movie: movie), mode: .edit) { result in
          if case .success(let action) = result, action == .delete {
            self.presentationMode.wrappedValue.dismiss()
          }
        }
      }
    }
    
  }

struct MovieDetailsView_Previews: PreviewProvider {
    static var previews: some View {
        let movie = Movie(title: "title movie", description: "this is a sample description", year: "2021")
        return
          NavigationView {
            MovieDetailsView(movie: movie)
          }
    }
}
View/MovieEditView.swift
 
//
//  MovieEditView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI

enum Mode {
  case new
  case edit
}

enum Action {
  case delete
  case done
  case cancel
}

struct MovieEditView: View {
    @Environment(\.presentationMode) private var presentationMode
    @State var presentActionSheet = false
    
    @ObservedObject var viewModel = MovieViewModel()
    var mode: Mode = .new
    var completionHandler: ((Result<Action, Error>) -> Void)?
    
    
    var cancelButton: some View {
      Button(action: { self.handleCancelTapped() }) {
        Text("Cancel")
      }
    }
    
    var saveButton: some View {
      Button(action: { self.handleDoneTapped() }) {
        Text(mode == .new ? "Done" : "Save")
      }
      .disabled(!viewModel.modified)
    }
    
    var body: some View {
      NavigationView {
        Form {
          Section(header: Text("Movie")) {
            TextField("Title", text: $viewModel.movie.title)
            TextField("Year", text: $viewModel.movie.year)
          }
          
          Section(header: Text("Description")) {
            TextField("Description", text: $viewModel.movie.description)
          }
          
          if mode == .edit {
            Section {
              Button("Delete Movie") { self.presentActionSheet.toggle() }
                .foregroundColor(.red)
            }
          }
        }
        .navigationTitle(mode == .new ? "New Movie" : viewModel.movie.title)
        .navigationBarTitleDisplayMode(mode == .new ? .inline : .large)
        .navigationBarItems(
          leading: cancelButton,
          trailing: saveButton
        )
        .actionSheet(isPresented: $presentActionSheet) {
          ActionSheet(title: Text("Are you sure?"),
                      buttons: [
                        .destructive(Text("Delete Movie"),
                                     action: { self.handleDeleteTapped() }),
                        .cancel()
                      ])
        }
      }
    }
    
    // Action Handlers
    
    func handleCancelTapped() {
      self.dismiss()
    }
    
    func handleDoneTapped() {
      self.viewModel.handleDoneTapped()
      self.dismiss()
    }
    
    func handleDeleteTapped() {
      viewModel.handleDeleteTapped()
      self.dismiss()
      self.completionHandler?(.success(.delete))
    }
    
    func dismiss() {
      self.presentationMode.wrappedValue.dismiss()
    }
  }

//struct MovieEditView_Previews: PreviewProvider {
//    static var previews: some View {
//        MovieEditView()
//    }
//}

struct MovieEditView_Previews: PreviewProvider {
  static var previews: some View {
    let movie = Movie(title: "Sample title", description: "Sample Description", year: "2020")
    let movieViewModel = MovieViewModel(movie: movie)
    return MovieEditView(viewModel: movieViewModel, mode: .edit)
  }
}

SwiftUI Firebase Fetch data and display in a List

SwiftUI Firebase Fetch data and display in a List

In this tutorial we will learn how to display firebase data in List

ContentView.swift
 
//
//  ContentView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
 

struct ContentView: View {
    
    @ObservedObject private var viewModel = userViewModel()
    
    var body: some View {
        NavigationView {
            List(viewModel.users) { user in
                VStack(alignment: .leading) {
                    Text(user.name).font(.title)
                    Text(user.surname).font(.subheadline)
                }
            }.navigationBarTitle("Users")
            .onAppear() {
                self.viewModel.fetchData()
            }
        }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
User.swift
 
//
//  User.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import Foundation

struct User: Identifiable {
    var id: String = UUID().uuidString
    var name: String
    var surname: String
}
UserViewModel.swift
 
//
//  UserViewModel.swift
//  DevSwiftUI
//
//  Created by Cairocoders 
//

import Foundation
import FirebaseFirestore

class userViewModel: ObservableObject {
    
    @Published var users = [User]()
    
    private var db = Firestore.firestore()
    
    func fetchData() {
        db.collection("users").addSnapshotListener { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("No documents")
                return
            }
            
            self.users = documents.map { (queryDocumentSnapshot) -> User in
                let data = queryDocumentSnapshot.data()
                let name = data["name"] as? String ?? ""
                let surname = data["surname"] as? String ?? ""
                return User(name: name, surname: surname)
            }
        }
    }
}
DevSwiftUIApp.swift
 
//
//  DevSwiftUIApp.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import Firebase

@main
struct DevSwiftUIApp: App {
    
    init() {
    FirebaseApp.configure()
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Saturday, May 29, 2021

Jquery Ajax Live Editable Table using Python Flask PostgreSQL

Jquery Ajax Live Editable Table using Python Flask PostgreSQL

install psycopg2 https://pypi.org/project/psycopg2/
Psycopg is the most popular PostgreSQL database adapter for the Python programming language.
(venv) PS C:\flaskmyproject> pip install psycopg2

Create TABLE
CREATE TABLE users (
id serial PRIMARY KEY,
fullname VARCHAR ( 100 ) NOT NULL,
username VARCHAR ( 50 ) NOT NULL,
password VARCHAR ( 255 ) NOT NULL,
email VARCHAR ( 50 ) NOT NULL
);

app.py
 
#app.py
from flask import Flask, request, render_template, jsonify
import psycopg2 #pip install psycopg2 
import psycopg2.extras
  
app = Flask(__name__)
  
app.secret_key = "cairocoders-ednalan"
  
DB_HOST = "localhost"
DB_NAME = "sampledb"
DB_USER = "postgres"
DB_PASS = "admin"
  
conn = psycopg2.connect(dbname=DB_NAME, user=DB_USER, password=DB_PASS, host=DB_HOST)
  
@app.route('/')
def home():
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        cursor.execute("SELECT * from users order by id")
        userslist = cursor.fetchall()
        return render_template('index.html',userslist=userslist)
    except Exception as e:
        print(e)
    finally:
        cursor.close() 
 
@app.route("/update",methods=["POST","GET"])
def update():
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        if request.method == 'POST':
            field = request.form['field'] 
            value = request.form['value']
            editid = request.form['id']
             
            if field == 'username':
               sql = "UPDATE users SET username=%s WHERE id=%s"
            if field == 'name':        
                sql = "UPDATE users SET fullname=%s WHERE id=%s"
 
            data = (value, editid)
            cursor.execute(sql, data)
            conn.commit()
            success = 1
        return jsonify(success)
    except Exception as e:
        print(e)
    finally:
        cursor.close() 

if __name__ == "__main__":
    app.run()
templates/index.html
//templates/index.html
<!doctype html>
<html>
<head>
<title>Jquery Ajax Live Editable Table using Python Flask PostgreSQL</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />    
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type='text/javascript'>
$(document).ready(function(){
  
 // Show Input element
 $('.edit').click(function(){
  $('.txtedit').hide();
  $(this).next('.txtedit').show().focus();
  $(this).hide();
 });
 
 // Save data
 $(".txtedit").focusout(function(){
   
  // Get edit id, field name and value
  var id = this.id;
  var split_id = id.split("_");
  var field_name = split_id[0];
  var edit_id = split_id[1];
  var value = $(this).val();
   
  // Hide Input element
  $(this).hide();
 
  // Hide and Change Text of the container with input elmeent
  $(this).prev('.edit').show();
  $(this).prev('.edit').text(value);
 
  $.ajax({
   url: '/update',
   type: 'post',
   data: { field:field_name, value:value, id:edit_id },
   success:function(response){
      if(response == 1){ 
         console.log('Save successfully'); 
      }else{ 
         console.log("Not saved.");  
      }
   }
  });
  
 });
 
});
</script>
</head>
<body >
<div class="container" >
    <div class="row" style="padding:50px;">
        <p><h1>Jquery Ajax Live Editable Table using Python Flask PostgreSQL</h1></p>
        <table width='100%' border='0'>
         <tr>
          <th width='10%'>ID</th>
          <th width='40%'>Username</th>
          <th width='40%'>Name</th>
         </tr>
         {% for row in userslist %}    
         <tr>
          <td>{{row.id}}</td>
          <td> 
            <div class='edit' > {{row.username}}</div> 
            <input type='text' class='txtedit' value='{{row.username}}' id='username_{{row.id}}' >
          </td>
          <td> 
           <div class='edit' >{{row.fullname}} </div> 
           <input type='text' class='txtedit' value='{{row.fullname}}' id='name_{{row.id}}' >
          </td>
         </tr>
         {% endfor %} 
        </table>
   </div>
</div>
<style>
.edit{
 width: 100%;
 height: 25px;
}
.editMode{
 border: 1px solid black;
}
table {
 border:3px solid lavender;
 border-radius:3px;
}
table tr:nth-child(1){
 background-color:#4285f4;
}
table tr:nth-child(1) th{
 color:white;
 padding:10px 0px;
 letter-spacing: 1px;
}
table td{
 padding:10px;
}
table tr:nth-child(even){
 background-color:lavender;
 color:black;
}
.txtedit{
 display: none;
 width: 99%;
 height: 30px;
}
</style>
</body>
</html>

DataTable AJAX using Python Flask PostgreSQL

DataTable AJAX using Python Flask PostgreSQL

Download Datatables from here. https://datatables.net/download/

install psycopg2 https://pypi.org/project/psycopg2/
Psycopg is the most popular PostgreSQL database adapter for the Python programming language.
(venv) PS C:\flaskmyproject> pip install psycopg2

CREATE TABLE employee (
id serial PRIMARY KEY,
name VARCHAR ( 100 ) NOT NULL,
position VARCHAR ( 100 ) NOT NULL,
office VARCHAR ( 100 ) NOT NULL,
age INT NOT NULL,
salary INT NOT NULL,
photo VARCHAR ( 150 ) NOT NULL,
);


INSERT INTO
    employee(name, position, office, age, salary, photo)
VALUES
('Tiger Wood', 'Accountant', 'Tokyo', 36, 5689, '01.jpg'),
('Mark Oto Ednalan', 'Chief Executive Officer (CEO)', 'London', 56, 5648, '02.jpg'),
('Jacob thompson', 'Junior Technical Author', 'San Francisco', 23, 5689, '03.jpg'),
('cylde Ednalan', 'Software Engineer', 'Olongapo', 23, 54654, '04.jpg'),
('Rhona Davidson', 'Software Engineer', 'San Francisco', 26, 5465, '05.jpg'),
('Quinn Flynn', 'Integration Specialist', 'New York', 53, 56465, '06.jpg'),
('Tiger Nixon', 'Software Engineer', 'London', 45, 456, '07.jpg'),
('Airi Satou', 'Pre-Sales Support', 'New York', 25, 4568, '08.jpg'),
('Angelica Ramos', 'Sales Assistant', 'New York', 45, 456, '09.jpg'),
('Ashton updated', 'Senior Javascript Developer', 'Olongapo', 45, 54565, '01.jpg'),
('Bradley Greer', 'Regional Director', 'San Francisco', 27, 5485, '02.jpg'),
('Brenden Wagner', 'Javascript Developer', 'San Francisco', 38, 65468, '03.jpg'),
('Brielle Williamson', 'Personnel Lead', 'Olongapo', 56, 354685, '04.jpg'),
('Bruno Nash', 'Customer Support', 'New York', 36, 65465, '05.jpg'),
('cairocoders', 'Sales Assistant', 'Sydney', 45, 56465, '06.jpg'),
('Zorita Serrano', 'Support Engineer', 'San Francisco', 38, 6548, '07.jpg'),
('Zenaida Frank', 'Chief Operating Officer (COO)', 'San Francisco', 39, 545, '08.jpg'),
('Sakura Yamamoto', 'Support Engineer', 'Tokyo', 48, 5468, '05.jpg'),
('Serge Baldwin', 'Data Coordinator', 'Singapore', 85, 5646, '05.jpg'),
('Shad Decker', 'Regional Director', 'Tokyo', 45, 4545, '05.jpg');
app.py
 
#app.py
from flask import Flask, request, render_template, jsonify, json
import psycopg2 #pip install psycopg2 
import psycopg2.extras
  
app = Flask(__name__)
  
app.secret_key = "cairocoders-ednalan"
  
DB_HOST = "localhost"
DB_NAME = "sampledb"
DB_USER = "postgres"
DB_PASS = "admin"
  
conn = psycopg2.connect(dbname=DB_NAME, user=DB_USER, password=DB_PASS, host=DB_HOST)
  
@app.route('/')
def home():
    return render_template('index.html')
 
@app.route("/ajaxfile",methods=["POST","GET"])
def ajaxfile():
    try:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        if request.method == 'POST':
            draw = request.form['draw'] 
            row = int(request.form['start'])
            rowperpage = int(request.form['length'])
            searchValue = request.form["search[value]"]
            #print(draw)
            print(row)
            print(rowperpage)
            #print(searchValue)
 
            ## Total number of records without filtering
            cursor.execute("select count(*) as allcount from employee")
            rsallcount = cursor.fetchone()
            totalRecords = rsallcount['allcount']
            print(totalRecords) 
 
            ## Total number of records with filtering
            #likeString = "%" + searchValue + "%"

            likeString = "{}%".format(searchValue)

            print(likeString)
            cursor.execute("SELECT count(*) as allcount from employee WHERE name LIKE %s", (likeString,))
            rsallcount = cursor.fetchone()
            totalRecordwithFilter = rsallcount['allcount']
            print(totalRecordwithFilter) 
 
            ## Fetch records
            if searchValue=='':
                cursor.execute('SELECT * FROM employee LIMIT {limit} OFFSET {offset}'.format(limit=rowperpage, offset=row))
                employeelist = cursor.fetchall()
            else:        
                cursor.execute("SELECT * FROM employee WHERE name LIKE %s LIMIT %s OFFSET %s;", (likeString, rowperpage, row,))

                employeelist = cursor.fetchall()
 
            data = []
            for row in employeelist:
                data.append({
                    'name': row['name'],
                    'position': row['position'],
                    'age': row['age'],
                    'salary': row['salary'],
                    'office': row['office'],
                })
 
            response = {
                'draw': draw,
                'iTotalRecords': totalRecords,
                'iTotalDisplayRecords': totalRecordwithFilter,
                'aaData': data,
            }
            return jsonify(response)
    except Exception as e:
        print(e)
    finally:
        cursor.close() 
 
if __name__ == "__main__":
    app.run()
templates/index.html
//templates/index.html
<!doctype html>
<html>
<head>
<title>DataTable AJAX using Python Flask PostgreSQL</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />    
<link href='https://cdn.datatables.net/1.10.24/css/jquery.dataTables.min.css' rel='stylesheet' type='text/css'>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.24/js/jquery.dataTables.min.js"></script>
</head>
<body >
<div class="container" >
    <div class="row" style="padding:50px;">
        <p><h1>DataTable AJAX using Python Flask PostgreSQL</h1></p>
        <div >
            <table id='empTable' class='display dataTable' width='100%'>
                <thead>
                <tr>
                    <th>Employee Name</th>
                    <th>Position</th>
                    <th>Age</th>
                    <th>Salary</th>
                    <th>Office</th>
                </tr>
                </thead>
                 
            </table>
        </div>
   </div>
</div>
<script>
$(document).ready(function() {
    var empDataTable = $('#empTable').DataTable({
                'processing': true,
                'serverSide': true,
                'serverMethod': 'post',
                'ajax': {
                    'url':'/ajaxfile'
                },
                'lengthMenu': [[5, 10, 25, 50, -1], [5, 10, 25, 50, "All"]],
                searching: true,
                sort: false,
                "serverSide": true,
                'columns': [
                    { data: 'name' },
                    { data: 'position' },
                    { data: 'age' },
                    { data: 'salary' },
                    { data: 'office' },
                ]
            });
});
</script>
</body>
</html>

SwiftUI Onboarding View using PageTabViewStyle

SwiftUI Onboarding View using PageTabViewStyle

ContentView.swift
 
//
//  ContentView.swift
//  Devapp
//
//  Created by Cairocoders
//

import SwiftUI //

struct ContentView: View {
    
    @State private var isOnboardinDone: Bool = false

    var body: some View {
        if isOnboardinDone {
            HomeView()
        } else if !isOnboardinDone {
            SplashView(done: $isOnboardinDone)
        } else {
            HomeView()
        }
        
    }
}

struct details_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


struct HomeView: View {

    @State private var showpopover = false

    var body: some View {
        Button("Show menu") {
            showpopover = true
        }
        .popover(isPresented: $showpopover) {
            VStack(alignment: .leading,spacing: 7.0){
                HStack(spacing: 15){
                    Button(action: {}, label: {
                        HStack {
                            Image(systemName: "paperplane.circle")
                                .font(.largeTitle)
                            Text("Submit")
                                .fontWeight(.heavy)
                                .foregroundColor(.white)
                                .padding(.vertical)
                                .frame(maxWidth: .infinity)
                        }
                        .background(Color.blue)
                        .foregroundColor(.white)
                        .cornerRadius(15)
                    })

                    
                    Button(action: {
                        withAnimation{

                        }
                    }, label: {
                        HStack {
                            Image(systemName: "arrowshape.turn.up.forward.circle")
                                .font(.largeTitle)
                            Text("Next")
                                .fontWeight(.heavy)
                                .foregroundColor(.white)
                                .padding(.vertical)
                                .frame(maxWidth: .infinity)
                        }
                        .background(Color.green)
                        .foregroundColor(.white)
                        .cornerRadius(15)
                    })
               } //End HStack
               .padding(.bottom)
            }//End VStack
            .padding()
        }
           
    }
}

struct SplashView: View {
    
    @Binding var done: Bool
    @State private var currentTab = 0

    var body: some View {
        TabView(selection: $currentTab,
                content:  {
                    ForEach(OnboardingData.list) { viewData in
                        OnboardingView(data: viewData, done: $done)
                            .tag(viewData.id)
                    }
                })
            .tabViewStyle(PageTabViewStyle())
            .indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
            .background(
                LinearGradient(gradient: Gradient(colors: [.blue, .white, .yellow]), startPoint: .topLeading, endPoint: .bottomTrailing)
            )
    }
}
OnboardingData.swift
 
//
//  OnboardingData.swift
//  Devapp
//
//  Created by Cairocoders
//

import Foundation

struct OnboardingData: Hashable, Identifiable {
    let id: Int
    let backgroundImage: String
    let primaryText: String
    let secondaryText: String

    static let list: [OnboardingData] = [
        OnboardingData(id: 0, backgroundImage: "pic1", primaryText: "Online Course", secondaryText: "Online Course any place anytime"),
        OnboardingData(id: 1, backgroundImage: "pic2", primaryText: "Kick start your learning", secondaryText: "Kick start your learning Development"),
        OnboardingData(id: 2, backgroundImage: "pic3", primaryText: "Learn SwiftUI", secondaryText: "Learn SwiftUI beginners to advance")
    ]
}
OnboardingView.swift
 
//
//  OnboardingView.swift
//  Devapp
//
//  Created by Cairocoders
//

import SwiftUI


struct OnboardingView: View {
    
    var data: OnboardingData
    
    @Binding var done: Bool

    @State private var isAnimating: Bool = false
    
    var body: some View {
        VStack(spacing: 20) {
            ZStack {
                Image(data.backgroundImage)
                    .resizable()
                    .scaledToFit()
            }

            Spacer()
            Spacer()

            Text(data.primaryText)
                .font(.title2)
                .bold()
                .foregroundColor(Color.black)

            Text(data.secondaryText)
                .font(.headline)
                .multilineTextAlignment(.center)
                .frame(maxWidth: 250)
                .foregroundColor(Color.black)

            Spacer()
            
            Button(action: { done.toggle() }, label: {
                Text("Get Started")
                    .font(.headline)
                    .foregroundColor(.white)
                    .padding(.horizontal, 50)
                    .padding(.vertical, 16)
                    .background(Color.green)
                    .foregroundColor(.white)
                    .cornerRadius(15)
            })
            .shadow(radius: 10)

            Spacer()
        }
        .onAppear(perform: {
            isAnimating = false
            withAnimation(.easeOut(duration: 0.5)) {
                self.isAnimating = true
            }
        })
    }
}

Wednesday, May 26, 2021

SwiftUI Splash Screen tap start button goto HomepageView

SwiftUI Splash Screen tap start button goto HomepageView
 
//
//  ContentView.swift
//  Devapp
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    
    @State private var isOnboardinDone: Bool = false

    var body: some View {
        
        if isOnboardinDone {
            Homepage()
        } else if !isOnboardinDone {
            OnboardingView(done: $isOnboardinDone)
        } else {
            Homepage()
        }
       
    }

}

struct details_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct Homepage: View {
    
    var body: some View {
        NavigationView {
            List {
                Text("Episode IV – A New Hope")
                Text("Episode V – The Empire Strikes Back")
                Text("Episode VI – Return of the Jedi")
            }
            .navigationTitle("Home")
        }
    }
}


struct OnboardingView: View {
    
    @Binding var done: Bool

    var body: some View {
        ScrollView {
            VStack(alignment: .center) {

                Spacer()

                TitleView()

                InformationContainerView()

                Spacer(minLength: 30)
                
                Button(action: { done.toggle() }, label: {
                    Text("Start")
                        .customButton()
                })
                .padding(.horizontal)
                
            }
        }
    }
}

struct InformationDetailView: View {
    var title: String = "title"
    var subTitle: String = "subTitle"
    var imageName: String = ""

    var body: some View {
        HStack(alignment: .center) {
            Image(systemName: imageName)
                .font(.largeTitle)
                .foregroundColor(.mainColor)
                .padding()
                .accessibility(hidden: true)

            VStack(alignment: .leading) {
                Text(title)
                    .font(.headline)
                    .foregroundColor(.primary)
                    .accessibility(addTraits: .isHeader)

                Text(subTitle)
                    .font(.body)
                    .foregroundColor(.secondary)
                    .fixedSize(horizontal: false, vertical: true)
            }
        }
        .padding(.top)
    }
}

struct InformationContainerView: View {
    var body: some View {
        VStack(alignment: .leading) {
            InformationDetailView(title: "Splash Screen", subTitle: "Onboarding screen is shown (OnboardingView)", imageName: "desktopcomputer")

            InformationDetailView(title: "Start Button", subTitle: "By tapping Start Button Go to home page (HomeView)", imageName: "forward.frame.fill")

            InformationDetailView(title: "Start App", subTitle: "Splash Screen Start the application", imageName: "iphone")
        }
        .padding(.horizontal)
    }
}

struct TitleView: View {
    var body: some View {
        VStack {
            Image("pic1")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 180, alignment: .center)
                .accessibility(hidden: true)

            Text("Welcome")
                .customTitleText()

            Text("Take Some time out")
                .customTitleText()
                .foregroundColor(.mainColor)
        }
    }
}

struct ButtonModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .foregroundColor(.white)
            .font(.headline)
            .padding()
            .frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
            .background(RoundedRectangle(cornerRadius: 15, style: .continuous)
                .fill(Color.mainColor))
            .padding(.bottom)
    }
}

extension View {
    func customButton() -> ModifiedContent<Self, ButtonModifier> {
        return modifier(ButtonModifier())
    }
}

extension Text {
    func customTitleText() -> Text {
        self
            .fontWeight(.black)
            .font(.system(size: 36))
    }
}

extension Color {
    static var mainColor = Color(UIColor.systemGreen)
}

SwiftUI Carousel Slider Welcome Page

SwiftUI Carousel Slider Welcome Page
 
//
//  ContentView.swift
//  Devapp
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        Home()
    }
}

struct details_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct Home: View {
    
    @State var CurrentIndex : Int = 1
    
    var body: some View {
        VStack {
            
            //Carousel Slider
            TabView(selection: $CurrentIndex) {
                ForEach(1...3,id: \.self) {index in
                    
                    //Custom Scroll Effect
                    GeometryReader{proxy -> AnyView in
                        
                        let minX = proxy.frame(in: .global).minX
                        
                        let width = UIScreen.main.bounds.width
                        
                        let progress = -minX / (width * 2)
                        
                        var scale = progress > 0 ? 1 - progress : 1 + progress
                        
                        scale = scale < 0.7 ? 0.7 : scale
                        
                        return AnyView(
                            VStack{
                                Image("pic\(index)")
                                    .resizable()
                                    .aspectRatio(contentMode: .fit)
                                    .padding(.horizontal,10)
                                
                                Text("Loren ipsum dlipsum")
                                    .font(.largeTitle)
                                    .fontWeight(.heavy)
                                    .foregroundColor(.white)
                                    //.background(Color.green)
                                    .padding()
                                
                                Text("Loren ipsum, or dlipsum as is somtine know text usded in layoyt Loren ipsum, or dlipsum as is somtine know text usded in layoyt")
                                    .font(.system(size: 16, weight: .bold))
                                    .foregroundColor(.white)
                                    .padding(.horizontal)
                                    
                            }
                            .frame(maxHeight: .infinity, alignment: .center)
                            .scaleEffect(scale)
                        )
                    }
                    .tag(index)
                }
            }
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
            
            //custom tab indicator
            
            CustomeTabIndicator(count: 3, current: $CurrentIndex)
                .padding(.vertical)
                .padding(.top)
            
            VStack(spacing:15) {
                
                Button(action: {}, label: {
                    HStack{
                        Image(systemName: "arrow.right.square")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 25, height: 25)
                            .foregroundColor(.white)
                        
                        Text("Start")
                            .fontWeight(.bold)
                            .foregroundColor(.white)
                            .frame(maxWidth: .infinity, alignment: .center)
                    }
                    .padding(.vertical,13)
                    .padding(.horizontal)
                    .background(
                        RoundedRectangle(cornerRadius: 10)
                            .fill(Color.black)
                            .overlay(
                                RoundedRectangle(cornerRadius: 10)
                                    .stroke(Color.white,lineWidth: 1)
                            )
                    )
                })
            }
            .padding()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.blue).ignoresSafeArea()
    }
}

struct CustomeTabIndicator: View {
    
    var count: Int
    @Binding var current: Int
    
    var body: some View {
        
        HStack {
            
            HStack {
                ForEach(0..<count,id: \.self) { index in
                    
                    ZStack {
                        //image  index start from 1..
                        if (current - 1) == index {
                            Circle()
                                .fill(Color.green)
                        }
                        else {
                            
                            Circle()
                                .fill(Color.white)
                                .overlay(
                                    Circle()
                                        .stroke(Color.green, lineWidth: 1.5)
                                )
                        }
                    }
                    .frame(width: 10, height: 10)
                }
            }
        }
    }
}

SwiftUI how to call a function when button pressed

SwiftUI how to call a function when button pressed
 
//
//  ContentView.swift
//  Testapp
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {

    @State private var count = 0
    
    var body: some View {
        
        VStack {
            Button(action: {stepCount()
            }, label: {
                Text("Increment Count")
                    .fontWeight(.heavy)
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.blue)
                    .cornerRadius(15)
            })
            
            Text("The count is: \(self.count)")
        }
    } // End body
    
    func stepCount() {
        count += 1
    }
    
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

SwiftUI Grid Layout Using LazyVGrid

SwiftUI Grid Layout Using LazyVGrid
 
//
//  ContentView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
 
struct Photo: Identifiable {
    var id = UUID()
    var name: String
}

let listphotoloop = (1...11).map { Photo(name: "\($0)") } //1.jpg to 11.jpg Assets.xcassets

struct ContentView: View {
     
    @State var gridLayout: [GridItem] = [GridItem(.flexible()), GridItem(.flexible())]
     
 
    var body: some View {
         
        NavigationView {
            ScrollView {
                LazyVGrid(columns: gridLayout, alignment: .center, spacing: 10) {
 
                    ForEach(listphotoloop.indices) { index in
                        
                        Image(listphotoloop[index].name)
                            .resizable()
                            .scaledToFill()
                            .frame(minWidth: 0, maxWidth: .infinity)
                            .frame(height: 200)
                            .cornerRadius(10)
                            .shadow(color: Color.primary.opacity(0.3), radius: 1)
                        
                    }
                } // End ScrollView
                .padding(.all, 10)
                .animation(.interactiveSpring())
                 
            }// End ScrollView
 
            .navigationTitle("Grid Layout Using LazyVGrid")
             
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button(action: {
                        self.gridLayout = Array(repeating: .init(.flexible()), count: self.gridLayout.count % 4 + 1)
                    }) {
                        Image(systemName: "square.grid.2x2")
                            .font(.title)
                            .foregroundColor(.primary)
                    }
                }
            }
             
        } // End Navigation
         
    } // End body
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Tuesday, May 25, 2021

SwiftUI how to add URL image

SwiftUI how to add URL image
 
//
//  ContentView.swift
//  Testapp
//
//  Created by Cairocoders
//

import SwiftUI


struct ContentView: View {
    
    let getURL = "https://images.pexels.com/photos/3225517/pexels-photo-3225517.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"

    var body: some View {
        URLImage(url: getURL)
            .aspectRatio(contentMode: .fit)
            .frame(width: 200)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct URLImage: View {
    private enum LoadState {
        case loading, success, failure
    }

    private class Loader: ObservableObject {
        var data = Data()
        var state = LoadState.loading

        init(url: String) {
            guard let parsedURL = URL(string: url) else {
                fatalError("Invalid URL: \(url)")
            }

            URLSession.shared.dataTask(with: parsedURL) { data, response, error in
                if let data = data, data.count > 0 {
                    self.data = data
                    self.state = .success
                } else {
                    self.state = .failure
                }

                DispatchQueue.main.async {
                    self.objectWillChange.send()
                }
            }.resume()
        }
    }

    @StateObject private var loader: Loader
    var loading: Image
    var failure: Image

    var body: some View {
        selectImage()
            .resizable()
    }

    init(url: String, loading: Image = Image(systemName: "photo"), failure: Image = Image(systemName: "multiply.circle")) {
        _loader = StateObject(wrappedValue: Loader(url: url))
        self.loading = loading
        self.failure = failure
    }

    private func selectImage() -> Image {
        switch loader.state {
        case .loading:
            return loading
        case .failure:
            return failure
        default:
            if let image = UIImage(data: loader.data) {
                return Image(uiImage: image)
            } else {
                return failure
            }
        }
    }
}

SwiftUI how to add button to navigation bar

SwiftUI how to add button to navigation bar

Ho to add buttons and images to navigation bar in swiftUI NavigationView

 
//
//  ContentView.swift
//  Testapp
//
//  Created by Cairocoders
//

import SwiftUI


struct ContentView: View {
    
    @State var showAlert: Bool = false
    @State var msg: String = ""
    
    var body: some View {
        NavigationView {
            Text("Cairocoders - tutorial101.blogspot.com")

            .navigationBarTitle("Tutorials")
            .navigationBarItems(trailing:
                HStack {
                        Button(action: {
                            self.showAlert = true
                            self.msg = "Reload button pressed..."
                        }) {
                            Text("Reload")
                        }
                        
                        Button(action: {
                            self.showAlert = true
                            self.msg = "Edit button pressed..."
                        }) {
                            Image(systemName: "person.crop.circle").imageScale(.large) //SF Symbol
                        }
                }
            )
        }
        .alert(isPresented: $showAlert, content: {
            Alert(title: Text(self.msg))
        })
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Monday, May 24, 2021

SwiftUI Horizontal scroll or horizontal list view

SwiftUI Horizontal scroll or horizontal list view
 
//
//  ContentView.swift
//  Testapp
//
//  Created by Cairocoders
//

import SwiftUI


struct ContentView: View {

    
    var body: some View {
        VStack {
            Divider()
            ScrollView(.horizontal) {
                HStack(spacing: 10) {
                    ForEach(0..<21) { index in
                        NumberView1to20(label: "\(index)")
                    }
                }.padding()
            }.frame(height: 100)
            Divider()
            Spacer()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct NumberView1to20: View {
    @State var label: String
    
    var body: some View {
        ZStack {
            Circle()
                .fill(Color.green)
                .frame(width: 70, height: 70)
            Text(label)
                .foregroundColor(.white)
        }
    }
}

Local storage UserDefaults CRUD Create Read Update Delete

A simple app Swift UI that allow to create, read,upate and delete value in local storage using UserDefaults

ContentView.swift
 
//
//  ContentView.swift
//  Testapp
//
//  Created by Cairocoders 
//

import SwiftUI


struct ContentView: View {

    @State var showAlert: Bool = false
    
    var body: some View {
        NavigationView {
            VStack {
                
                Text("Local storage UserDefaults CRUD Create Read Update Delete")
                    .font(.largeTitle)
                    .bold()
                    .padding(.bottom, 50)
                
                HStack {
                    
                    NavigationLink (destination: AddView(), label: {
                        Text("Add")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding()
                            .background(Color.green)
                    })
                    
                    NavigationLink (destination: DataView(), label: {
                        Text("View")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding()
                            .background(Color.green)
                    })
                    
                    NavigationLink (destination: EditView(), label: {
                        Text("Edit")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding()
                            .background(Color.green)
                    })
                    
                    Button(action: {
                        LocalStorage.removeValue() //Delete a value from local storage
                        self.showAlert = true
                    }, label: {
                        Text("Delete")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding()
                            .background(Color.green)
                    })
                }
            }
            .alert(isPresented: $showAlert, content: {
                Alert(title: Text("Data has been removed"))
            })
        }
    }
    

}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
LocalStorage.swift

This file will handle the creating, fetching, updating and deleting the data from local storage.

 
//
//  LocalStorage.swift
//  Testapp
//
//  Created by Cairocoders
//

import Foundation

class LocalStorage {
    
    private static let myKey: String = "myKey" //static constant named
    
    public static var myValue: String {
        set {
            UserDefaults.standard.set(newValue, forKey: myKey)
        }
        get {
            return UserDefaults.standard.string(forKey: myKey) ?? ""
        }
    }
    
    public static func removeValue() {
        UserDefaults.standard.removeObject(forKey: myKey) //removeValue() remove that value from UserDefaults.
    }
    
}
AddView.swift
 
//
//  AddView.swift
//  Testapp
//
//  Created by Cairocoders
//

import SwiftUI

struct AddView: View {
    @State var value: String = ""
    @State var showAlert: Bool = false
    
    var body: some View {
        VStack {
            TextField("Enter value", text: $value)
                .padding(10)
                .background(Color(.systemGray6))
                .cornerRadius(5)
                .disableAutocorrection(true)
            Button(action: {
                LocalStorage.myValue = self.value //Add value to local storage
                self.showAlert = true
            }, label: {
                Text("Save")
            })
        }
        .padding()
        .alert(isPresented: $showAlert, content: {
            Alert(title: Text("Data has been saved"))
        })
    }
}

struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        AddView()
    }
}
DataView..swift
 
//
//  DataView..swift
//  Testapp
//
//  Created by Cairocoders
//

import SwiftUI

struct DataView: View {
    var body: some View {
        Text(LocalStorage.myValue) //Get value from local storage
    }
}

struct DataView_Previews: PreviewProvider {
    static var previews: some View {
        DataView()
    }
}
EditView.swift
 
//
//  EditView.swift
//  Testapp
//
//  Created by Cairocoders
//

import SwiftUI

struct EditView: View {
    @State var value: String = ""
    @State var showAlert: Bool = false
    
    var body: some View {
        VStack {
            TextField("Enter value", text: $value)
                .padding(10)
                .background(Color(.systemGray6))
                .cornerRadius(5)
                .disableAutocorrection(true)
            Button(action: {
                LocalStorage.myValue = self.value
                self.showAlert = true
            }, label: {
                Text("Update")
            })
        }
        .padding()
        .onAppear(perform: {
            self.value = LocalStorage.myValue //Edit value in local storage
        })
        .alert(isPresented: $showAlert, content: {
            Alert(title: Text("Data has been updated"))
        })
    }
}

struct EditView_Previews: PreviewProvider {
    static var previews: some View {
        EditView()
    }
}

Thursday, May 20, 2021

SwiftUI How to add a Launch Screen

SwiftUI How to add a Launch Screen

Monday, May 17, 2021

SwiftUI Firebase Auth using firebase-ios-sdk

SwiftUI Firebase Auth using firebase-ios-sdk

https://console.firebase.google.com/
https://github.com/firebase/firebase-ios-sdk
 
//
//  Firebase_AuthApp.swift
//  Firebase Auth
//
//  Created by Cairocoders
//

import SwiftUI
import Firebase

@main
struct Firebase_AuthApp: App {
    init() {
        FirebaseApp.configure()
    }
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
 
//
//  ContentView.swift
//  Firebase Auth
//
//  Created by Cairocoders
//

import SwiftUI
import Firebase

struct ContentView: View {
    @State var email = ""
    @State var password = ""
    
    var body: some View {
        VStack {
            TextField("Email", text: $email)
            SecureField("Password", text: $password)
            Button(action: { login() }) {
                Text("Sign In")
            }
        }
        .padding()
    }
    
    func login(){
        Auth.auth().signIn(withEmail: email, password: password) { result, error in
            if error != nil {
                print(error?.localizedDescription ?? "")
            }else {
                print("success")
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

SwiftUI Popover

SwiftUI Popover
 
//
//  ContentView.swift
//  Testapp
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    
    @State var isPopoverPresented = false

    var body: some View {

        Button(action: {
            self.isPopoverPresented = true
        }) {
            Text("Show Popover")
        }

        .popover(isPresented: $isPopoverPresented) {
            Text("Popover is Presented")
                .font(.largeTitle)
                .frame(width: 500, height: 500)
        }
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Related Post