article

Friday, October 8, 2021

SwiftUI Simple Social App

SwiftUI Simple Social App

ContentView.swift
//
//  ContentView.swift
//  Swiftuitest
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        NavigationView {
            List {
                VStack(alignment: .leading) {
                    HStack {
                        Text("Trending")
                            .font(.title.bold())
                        Spacer()
                    }
                    
                    ScrollView(.horizontal, showsIndicators: false) {
                        LazyHStack(spacing: 15) {
                            ForEach(stories) { post in
                                StoryListCell(story: post)
                            }
                        }
                        .frame(height: 145)
                    }
                }
                Section {
                    ForEach(latestpost) { latespost in
                        PostListCell(post: latespost)
                    }
                }
            
            }.padding(.horizontal, -20)
           .navigationTitle(Text("Social App"))
        }
    }
}

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

import SwiftUI

struct StoryListCell : View {
    
    var story: Story
    
    var body: some View {
        ZStack {
            VStack(alignment: .leading) {
                Image(story.image)
                    .resizable()
                    .clipped()
                    .cornerRadius(6)
                
                Text(story.name)
                    .multilineTextAlignment(.center)
                    .lineLimit(nil)
                    .padding(.leading, 0)
                    .font(.caption)
            }.frame(width: 110, height: 140)
            
            Circle().frame(width: 44, height: 44)
                .foregroundColor(Color.white)
                .position(x: 110 - 24, y: 24)
            
            Image("photo2")
                .resizable()
                .frame(width: 40, height: 40)
                .clipped()
                .clipShape(Circle())
                .position(x: (110-24), y: 24)
        }
    }
}
PostListCell.swift
//
//  PostListCell.swift
//  Swiftuitest
//
//  Created by Cairocoders
//

import SwiftUI

struct PostListCell : View {
    
    var post: BlogPosts
    
    var body: some View {
        
        VStack(alignment: .leading) {
            HStack {
                Image("photo1")
                    .resizable()
                    .frame(width: 50, height: 50)
                    .background(Color.yellow)
                    .clipShape(Circle())
                
                VStack(alignment: .leading) {
                    Text(post.name).font(.headline)
                    Text(post.time).font(.subheadline)
                }
            }.padding(.leading, 12).padding(.top, 20)
            
            Text(post.name)
                .lineLimit(nil)
                .padding([.leading, .trailing], 12)
            
            Image(post.image)
                .resizable()
                .frame(height: 200)
                .clipped()
        }.padding([.leading, .trailing], -20).padding(.bottom, -8)
    }
}
Story.swift
//
//  Story.swift
//  Swiftuitest
//
//  Created by Cairocoders
//

import SwiftUI

import Foundation
 
struct Story : Identifiable {
      
    var id : Int
    var name : String
    var image : String
}
  
var stories = [
  
    Story(id: 1, name: "Chicken Adobo", image: "1"),
    Story(id: 2, name: "Afritada", image: "2"),
    Story(id: 3, name: "Asado", image: "3"),
    Story(id: 4, name: "Barbeque", image: "4"),
    Story(id: 5, name: "Curry", image: "5"),
    Story(id: 6, name: "Chicken Inasal", image: "6"),
    Story(id: 4, name: "Menudo", image: "7"),
    Story(id: 8, name: "Sarciado", image: "8"),
]
Post.swift
//
//  Post.swift
//  Swiftuitest
//
//  Created by Cairocoders
//

import Foundation
 
struct BlogPosts : Identifiable {
      
    var id : Int
    var name : String
    var image : String
    var details : String
    var time : String
}
  
var latestpost = [
  
    BlogPosts(id: 0, name: "Bistek Tagalog", image: "1", details: "A dish made of strips of salted and peppered sirloin beef, usually flattened with a meat tenderizing tool, slowly cooked in soy sauce, calamansi juice, garlic and onions, a specialty of the Tagalog region", time: "Posted 3 days ago"),
    BlogPosts(id: 1, name: "Boogie flight", image: "2", details: "A boodle fight is a meal that dispenses with cutlery and dishes. Diners instead practice kamayan, Filipino for eating with the hands" , time: "Posted 3 days ago"),
    BlogPosts(id: 2, name: "Sinigang Na Baboy", image: "3", details: "Sinigang na baboy with Gabi is a Filipino pork soup with taro cooked in a sour broth." , time: "Posted 3 days ago"),
    BlogPosts(id: 3, name: "Ginisang Togue", image: "4", details: "Ginisang Togue is basically Sauteed Mung Bean Sprout with carrots, bell pepper, shrimp, and tofu." , time: "Posted 3 days ago"),
    BlogPosts(id: 4, name: "Ginisang Munggo (Monggo)", image: "5", details: "Munggo or Mung bean (or even green bean to some) is a seed of Vigna radiata, a plant native to India and Pakistan. Since the plant originated in Asia, it was easy to spread along the nearby countries. This seed became a hit when it reached the Philippines." , time: "Posted 3 days ago"),
    BlogPosts(id: 5, name: "Pork Estofado (Sweet Pork Stew)", image: "6", details: "Pork Estofado with saba bananas, carrots, Chinese sausage, and a sweet and savory sauce. Perfect with steamed rice!" , time: "Posted 3 days ago"),
    BlogPosts(id: 6, name: "Pata Tim", image: "7", details: "Brimming in a pork stew infused with aromatic peppercorn, sesame oil and soy sauce, Pata Tim is a classic Filipino dish with traces in Chinese cuisine" , time: "Posted 3 days ago"),
    BlogPosts(id: 7, name: "Pancit Palabok", image: "8", details: "Pancit Palabok is a noodle dish with shrimp sauce and topped with several ingredients such as cooked shrimp, boiled pork, crushed chicharon, tinapa flakes, fried tofu, scallions, and fried garlic." , time: "Posted 3 days ago"),
]

Tuesday, October 5, 2021

SwiftUI Firebase CRUD (create-read-update-delete) book Library app

SwiftUI Firebase CRUD (create-read-update-delete) book Library app

In this tutorial i'm going to create a simple Library App CRUD (Create, Read, Update, and Delete) App Using Firebase With SwiftUI and SDWebImageSwiftUI

https://console.firebase.google.com/

SDWebImageSwiftUI
https://github.com/SDWebImage/SDWebImageSwiftUI.git

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

import SwiftUI
import Firebase
import SDWebImageSwiftUI

struct ContentView: View {
    
    @StateObject var viewModel = BooksViewModel()
    @State var presentAddBookSheet = false
    
    private var addButton: some View {
      Button(action: { self.presentAddBookSheet.toggle() }) {
        Image(systemName: "plus")
      }
    }
    
    private func bookRowView(book: Book) -> some View {
      NavigationLink(destination: BookDetailsView(book: book)) {
        VStack(alignment: .leading) {
            HStack {
                AnimatedImage(url: URL(string: book.image)!).resizable().frame(width: 65, height: 65).clipShape(Circle())
                
                VStack(alignment: .leading) {
                    Text(book.title)
                        .fontWeight(.bold)
                    Text(book.author)
                }
            }
        }
      }
    }
    
    var body: some View {
      NavigationView {
        List {
          ForEach (viewModel.books) { book in
            bookRowView(book: book)
          }
          .onDelete() { indexSet in
            viewModel.removeBooks(atOffsets: indexSet)
          }
        }
        .navigationBarTitle("Books")
        .navigationBarItems(trailing: addButton)
        .onAppear() {
          print("BooksListView appears. Subscribing to data updates.")
          self.viewModel.subscribe()
        }
        .sheet(isPresented: self.$presentAddBookSheet) {
          BookEditView()
        }
      }
    }
  }

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

import Foundation
import FirebaseFirestoreSwift

struct Book: Identifiable, Codable {
  @DocumentID var id: String?
  var title: String
  var author: String
  var numberOfPages: Int
  var image: String
  
  enum CodingKeys: String, CodingKey {
    case id
    case title
    case author
    case numberOfPages = "pages"
    case image
  }
}
BookDetailsView.swift
 
//
//  BookDetailsView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import SDWebImageSwiftUI

struct BookDetailsView: View {
  
  @Environment(\.presentationMode) var presentationMode
  @State var presentEditBookSheet = false
  
  
  var book: Book
  
  private func editButton(action: @escaping () -> Void) -> some View {
    Button(action: { action() }) {
      Text("Edit")
    }
  }
  
  var body: some View {
    Form {
      Section(header: Text("Book")) {
        Text(book.title)
        Text("\(book.numberOfPages) pages")
      }
      
      Section(header: Text("Author")) {
        Text(book.author)
      }
      Section(header: Text("Photo")) {
          AnimatedImage(url: URL(string: book.image)!).resizable().frame(width: 300, height: 300)
      }
    }
    .navigationBarTitle(book.title)
    .navigationBarItems(trailing: editButton {
      self.presentEditBookSheet.toggle()
    })
    .onAppear() {
      print("BookDetailsView.onAppear() for \(self.book.title)")
    }
    .onDisappear() {
      print("BookDetailsView.onDisappear()")
    }
    .sheet(isPresented: self.$presentEditBookSheet) {
      BookEditView(viewModel: BookViewModel(book: book), mode: .edit) { result in
        if case .success(let action) = result, action == .delete {
          self.presentationMode.wrappedValue.dismiss()
        }
      }
    }
  }
  
}

struct BookDetailsView_Previews: PreviewProvider {
  static var previews: some View {
    let book = Book(title: "Coder", author: "Cairocoders", numberOfPages: 23, image: "photo1")
    return
      NavigationView {
        BookDetailsView(book: book)
      }
  }
}
BookEditView.swift
 
//
//  BookEditView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI

enum Mode {
  case new
  case edit
}

enum Action {
  case delete
  case done
  case cancel
}

struct BookEditView: View {
  
  @Environment(\.presentationMode) private var presentationMode
  @State var presentActionSheet = false

  
  @ObservedObject var viewModel = BookViewModel()
  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("Book")) {
          TextField("Title", text: $viewModel.book.title)
          TextField("Number of pages", value: $viewModel.book.numberOfPages, formatter: NumberFormatter())
        }
        
        Section(header: Text("Author")) {
          TextField("Author", text: $viewModel.book.author)
        }

        Section(header: Text("Photo")) {
            TextField("Image", text: $viewModel.book.image)
        }
          
        if mode == .edit {
          Section {
            Button("Delete book") { self.presentActionSheet.toggle() }
              .foregroundColor(.red)
          }
        }
      }
      .navigationTitle(mode == .new ? "New book" : viewModel.book.title)
      .navigationBarTitleDisplayMode(mode == .new ? .inline : .large)
      .navigationBarItems(
        leading: cancelButton,
        trailing: saveButton
      )
      .actionSheet(isPresented: $presentActionSheet) {
        ActionSheet(title: Text("Are you sure?"),
                    buttons: [
                      .destructive(Text("Delete book"),
                                   action: { self.handleDeleteTapped() }),
                      .cancel()
                    ])
      }
    }
  }
  
  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 BookEditView_Previews: PreviewProvider {
  static var previews: some View {
    let book = Book(title: "Coder", author: "Cairocoders", numberOfPages: 89, image: "photo1")
    let bookViewModel = BookViewModel(book: book)
    return BookEditView(viewModel: bookViewModel, mode: .edit)
  }
}
BookViewModel.swift
 
//
//  BookViewModel.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import Foundation
import Combine
import FirebaseFirestore

class BookViewModel: ObservableObject {
  
  @Published var book: Book
  @Published var modified = false
  
  private var cancellables = Set<AnyCancellable>()
  
    init(book: Book = Book(title: "", author: "", numberOfPages: 0, image: "")) {
    self.book = book
    
    self.$book
      .dropFirst()
      .sink { [weak self] book in
        self?.modified = true
      }
      .store(in: &self.cancellables)
  }
  
  private var db = Firestore.firestore()
  
  private func addBook(_ book: Book) {
    do {
      let _ = try db.collection("books").addDocument(from: book)
    }
    catch {
      print(error)
    }
  }
  
  private func updateBook(_ book: Book) {
    if let documentId = book.id {
      do {
        try db.collection("books").document(documentId).setData(from: book)
      }
      catch {
        print(error)
      }
    }
  }
  
  private func updateOrAddBook() {
    if let _ = book.id {
      self.updateBook(self.book)
    }
    else {
      addBook(book)
    }
  }
  
  private func removeBook() {
    if let documentId = book.id {
      db.collection("books").document(documentId).delete { error in
        if let error = error {
          print(error.localizedDescription)
        }
      }
    }
  }
  
  func handleDoneTapped() {
    self.updateOrAddBook()
  }
  
  func handleDeleteTapped() {
    self.removeBook()
  }
  
}
BooksViewModel.swift
 
//
//  BooksViewModel.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import Foundation
import Combine
import FirebaseFirestore

class BooksViewModel: ObservableObject {
  @Published var books = [Book]()
  
  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("books").addSnapshotListener { (querySnapshot, error) in
        guard let documents = querySnapshot?.documents else {
          print("No documents")
          return
        }
        
        self.books = documents.compactMap { queryDocumentSnapshot in
          try? queryDocumentSnapshot.data(as: Book.self)
        }
      }
    }
  }
  
  func removeBooks(atOffsets indexSet: IndexSet) {
    let books = indexSet.lazy.map { self.books[$0] }
    books.forEach { book in
      if let documentId = book.id {
        db.collection("books").document(documentId).delete { error in
          if let error = error {
            print("Unable to remove document: \(error.localizedDescription)")
          }
        }
      }
    }
  }

  
}
DevSwiftUIApp.swift
 
//
//  DevSwiftUIApp.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import Firebase

@main
struct DevSwiftUIApp: App {

    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject,UIApplicationDelegate{
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        
        FirebaseApp.configure()
        return true
    }
}

SwiftUI Firebase Simple Tinder App

SwiftUI Firebase Simple Tinder App

In this tutorial i'm going to create a simple Tinder App Using Firebase With SwiftUI.

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

import SwiftUI
import Firebase
import SDWebImageSwiftUI

struct ContentView: View {
    
    @ObservedObject var obs = observer()
    @State var showLiked = false
    
    var body: some View {
       
        ZStack{
            Color(.white).edgesIgnoringSafeArea(.all)
            if obs.users.isEmpty{
                Loader()
            }
            
            VStack{
                TopView(show: $showLiked)
                swipeView()
            }
        }
        .sheet(isPresented: $showLiked) {
            LikedPeople()
        }
    }
}

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

import SwiftUI
import Firebase

class observer : ObservableObject{
  
  @Published var users = [datatype]()
  @Published var last = -1
  
  init() {
      
      let db = Firestore.firestore()
      
      db.collection("users").getDocuments { (snap, err) in
          
          if err != nil{
              print((err?.localizedDescription)!)
              return
          }
          
          for i in snap!.documents{
              
              let name = i.get("name") as! String
              let age = i.get("age") as! String
              let image = i.get("image") as! String
              let id = i.documentID
              let status = i.get("status") as! String
              
              if status == ""{
                  self.users.append(datatype(id: id, name: name, image: image, age: age, swipe: 0, degree: 0))
              }
          }
      }
  } //End init()
  
  func update(id : datatype,value : CGFloat,degree : Double){
      print("update \(id.id)")
      for i in 0..<self.users.count{
          
          if self.users[i].id == id.id{
              
              self.users[i].swipe = value
              self.users[i].degree = degree
              self.last = i
          }
      }
  }

  
  func updateDB(id : datatype,status : String){
      
      let db = Firestore.firestore()
      
      db.collection("users").document(id.id).updateData(["status":status]) { (err) in
          
          if err != nil{
              print(err!.localizedDescription)
              return
          }
          print("success \(id.id)")
          
          for i in 0..<self.users.count{
              if self.users[i].id == id.id{
                  if status == "liked"{
                      self.users[i].swipe = 500
                  }else if status == "dislike"{
                      self.users[i].swipe = -500
                  }else{
                      self.users[i].swipe = 0
                  }
              }
          }
          
          if status == "liked" {
              db.collection("liked").document(id.id).setData(["name":id.name,"age":id.age,"image":id.image]) { (err) in
                  if err != nil{
                      print((err?.localizedDescription)!)
                      return
                  }
              }
          }
          
      }
  }// End updateDB
}
datatypes.swift
 
//
//  datatypes.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import Foundation
import SwiftUI

struct datatype : Identifiable {
  
  var id : String
  var name : String
  var image : String
  var age : String
  var swipe : CGFloat
  var degree : Double
}

struct datatype1 : Identifiable {
  var id : String
  var name : String
  var age : String
  var image : String
}
TopView.swift
 
//
//  TopView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI

struct TopView : View {
  
  @Binding var show : Bool
    
  var body : some View{
        HStack(alignment: .top){
              
              Button(action: {
                  //No action
              }) {
                  Image("photo1").resizable().frame(width: 35, height: 35)
              }.foregroundColor(.gray)
              
              Spacer()
              
              Button(action: {
                  //No action
              }) {
                  Image(systemName: "flame.fill").resizable().frame(width: 30, height: 35)
              }.foregroundColor(.red)
              
              Spacer()
              
              Button(action: {
                  self.show.toggle()
              }) {
                  Image(systemName: "message").resizable().frame(width: 35, height: 35)
              }.foregroundColor(.gray)
              
        }.padding()
    }
}
swipeView.swift
 
//
//  swipeView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import SDWebImageSwiftUI

struct swipeView: View {
    
    @ObservedObject var obser = observer()
    
    var body : some View{
        VStack {
            GeometryReader{geo in
                
                ZStack{
                    
                    ForEach(self.obser.users){i in

                        SwipeDetailsView(name: i.name, age: i.age, image: i.image, height: geo.size.height - 100).gesture(DragGesture()
                        
                            .onChanged({ (value) in
                                if value.translation.width > 0{
                                    self.obser.update(id: i, value: value.translation.width, degree: 8)
                                }
                                else{
                                    self.obser.update(id: i, value: value.translation.width, degree: -8)
                                }
                            }).onEnded({ (value) in
                                if i.swipe > 0{
                                    if i.swipe > geo.size.width / 2 - 80{
                                        self.obser.update(id: i, value: 500, degree: 0)
                                    }
                                    else{
                                        self.obser.update(id: i, value: 0, degree: 0)
                                    }
                                }
                                else{
                                    if -i.swipe > geo.size.width / 2 - 80{
                                        self.obser.update(id: i, value: -500, degree: 0)
                                    }
                                    else{
                                        self.obser.update(id: i, value: 0, degree: 0)
                                    }
                                }
                            })
                        ).offset(x: i.swipe)
                        .rotationEffect(.init(degrees: i.degree))
                        .animation(.spring())
                    } //End Foreach
                }//End ZStack
            }// End GeometryReader
            
            HStack{
                Button(action: {
                    //No action
                }) {
                    Image(systemName: "arrow.clockwise.circle").resizable().frame(width: 25, height: 25).padding()
                }.foregroundColor(.yellow)
                .background(Color.white)
                .shadow(radius: 25)
                .clipShape(Circle())
                
                //dislike
                Button(action: {
                    if self.obser.last == -1{
                        self.obser.updateDB(id: self.obser.users[self.obser.users.count - 1], status: "dislike")
                    }
                    else{
                        self.obser.updateDB(id: self.obser.users[self.obser.last - 1], status: "dislike")
                    }
                }) {
                    Image(systemName: "xmark.circle").resizable().frame(width: 30, height: 30).padding()
                }.foregroundColor(.pink)
                .background(Color.white)
                .shadow(radius: 25)
                .clipShape(Circle())
                
                Button(action: {
                    //no action
                }) {
                    Image(systemName: "star").resizable().frame(width: 25, height: 25).padding()
                }.foregroundColor(.blue)
                .background(Color.white)
                .shadow(radius: 25)
                .clipShape(Circle())
                
                Button(action: {
                    if self.obser.last == -1{
                        self.obser.updateDB(id: self.obser.users[self.obser.users.count - 1], status: "liked")
                    }
                    else{
                        self.obser.updateDB(id: self.obser.users[self.obser.last - 1], status: "liked")
                    }
                }) {
                    Image(systemName: "heart").resizable().frame(width: 35, height: 35).padding()
                }.foregroundColor(.blue)
                .background(Color.white)
                .shadow(radius: 25)
                .clipShape(Circle())
                
                Button(action: {
                    //no action
                }) {
                    
                    Image(systemName: "rectangle.dashed.badge.record").resizable().frame(width: 25, height: 25).padding()
                    
                }.foregroundColor(.purple)
                .background(Color.white)
                .shadow(radius: 25)
                .clipShape(Circle())
            }
        }
    }
}

struct swipeView_Previews: PreviewProvider {
    static var previews: some View {
        swipeView()
    }
}
Loader.swift
 
//
//  Loader.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI

struct Loader : UIViewRepresentable {
  
  func makeUIView(context: UIViewRepresentableContext<Loader>) -> UIActivityIndicatorView {
      
      let indicator = UIActivityIndicatorView(style: .large)
      indicator.startAnimating()
      return indicator
  }
  
  func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<Loader>) {
      
      
  }
}
//
//  SwipeDetailsView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import SDWebImageSwiftUI

struct SwipeDetailsView: View {
    
    var name = ""
    var age = ""
    var image = ""
    var height : CGFloat = 0
    var body: some View {
        ZStack {
            AnimatedImage(url: URL(string: image)!).resizable().cornerRadius(20).padding(.horizontal, 15)
            
            VStack {
                
                Spacer()
                
                HStack {
                    VStack(alignment: .leading, content: {
                        Text(name).fontWeight(.heavy).font(.system(size: 25)).foregroundColor(.white)
                        Text(age).foregroundColor(.white)
                    })
                    Spacer()
                }
            }.padding([.bottom, .leading], 35)
            
        }.frame(height:height)
    }
}

struct SwipeDetailsView_Previews: PreviewProvider {
    static var previews: some View {
        SwipeDetailsView()
    }
}
likedPeople.swift
//
//  likedPeople.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import SDWebImageSwiftUI
import Firebase

struct LikedPeople: View {
  
  @ObservedObject var datas = observer1()
  var body: some View {
      
      VStack{
          if datas.data.isEmpty{
              Text("No Liked People")
          }
          else{
              NavigationView {
                  List(datas.data){i in
                      NavigationLink(destination : Details(userItem: i)) {
                          cards(name: i.name, image: i.image)
                      }
                  }.navigationBarTitle("Like Users")
              }
          }
      }
  }
}

struct cards : View {
  
  var name = ""
  var image = ""
  var body : some View{
      
      HStack{
          AnimatedImage(url: URL(string: image)!).resizable().frame(width: 65, height: 65).clipShape(Circle())
          Text(name).fontWeight(.heavy)
      }
  }
}

class observer1 : ObservableObject{
  
  @Published var data = [datatype1]()
  
  init() {
      
      let db = Firestore.firestore()
      db.collection("liked").getDocuments { (snap, err) in
          
          if err != nil{
              
              print((err?.localizedDescription)!)
              return
          }
          
          for i in snap!.documents{
              
              let name = i.get("name") as! String
              let age = i.get("age") as! String
              let image = i.get("image") as! String
              
              self.data.append(datatype1(id: UUID().uuidString, name: name, age: age, image: image))
          }
      }
  }
}
Details.swift
//
//  Details.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import SDWebImageSwiftUI

struct Details: View {
     
    let userItem : datatype1
    
    var body: some View {
        GeometryReader{geo in
            //Text(userItem.name)
            VStack {
                Text("Username : \(userItem.name)")
                    .font(.title2)
                  
                AnimatedImage(url: URL(string: userItem.image))
                    .resizable().frame(height: geo.size.height - 100)
                    .padding(.horizontal, 15)
                    .cornerRadius(20)
            }
        }
    }
}
DevSwiftUIApp.swift
//
//  DevSwiftUIApp.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import Firebase

@main
struct DevSwiftUIApp: App {

    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject,UIApplicationDelegate{
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        
        FirebaseApp.configure()
        return true
    }
}

Tuesday, September 28, 2021

ReactJS How to load data API in AG Grid React with loading content and Pagination

ReactJS How to load data API in AG Grid React with loading content and Pagination

In this tutorial we will create a load data API in AG Grid React with loading content and Pagination

AG Grid is a fully-featured and highly customizable JavaScript data grid. It delivers outstanding performance, has no 3rd party dependencies and integrates smoothly with React as React Component.

C:\reactdev\myreactdev>npm install --save ag-grid-community

https://www.npmjs.com/package/ag-grid-community

C:\reactdev\myreactdev>npm i --save ag-grid-community ag-grid-react react-dom-factories

https://www.npmjs.com/package/ag-grid-react

https://reqres.in/
Test your front-end against a real API

https://reqres.in/api/users
src/index.js
//src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
public/index.html
//public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>ReactJS </title>
  </head>
  <body>
    <div id="root"></div>
</body>
</html>
src/App.js
//src/App.js
import React, { useEffect, useState } from 'react';
import { AgGridColumn, AgGridReact } from 'ag-grid-react';

import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';

import './App.css';

function App() {
  const [gridApi, setGridApi] = useState(null);
  const perPage = 3;

  const onGridReady = (params) => {
    setGridApi(params.api);
  };

  useEffect(() => {
    if (gridApi) {
      const dataSource = {
        getRows: (params) => {
          // Use startRow and endRow for sending pagination to Backend
          // params.startRow : Start Page
          // params.endRow : End Page

          gridApi.showLoadingOverlay();
          const page = params.endRow / perPage;
          fetch(`https://reqres.in/api/users?per_page=${perPage}&page=${page}`)
            .then(resp => resp.json())
            .then(res => {
              if (!res.data.length) {
                gridApi.showNoRowsOverlay();
              }
              else {
                gridApi.hideOverlay();
              }
              params.successCallback(res.data, res.total);
            }).catch(err => {
              gridApi.showNoRowsOverlay();
              params.successCallback([], 0);
            });
        }
      }

      gridApi.setDatasource(dataSource);
    }
  }, [gridApi]);

  const avatarFormatter = ({ value }) => {
    return <img src={value} width="50px" height="50px" />
  }

  return (
    <div className="App">
      <h2>ReactJS How to load data API in AG Grid React with loading content and Pagination </h2>
      <div className="ag-theme-alpine ag-style">
        <AgGridReact
          pagination={true}
          rowModelType={'infinite'}
          paginationPageSize={perPage}
          cacheBlockSize={perPage}
          onGridReady={onGridReady}
          rowHeight={60}
          defaultColDef={{ flex: 1 }}
          overlayLoadingTemplate={
            '<span className="ag-overlay-loading-center">Please wait while your rows are loading...</span>'
          }
          overlayNoRowsTemplate={
            '<span className="ag-overlay-loading-center">No data found to display.</span>'
          }
        >
          <AgGridColumn field="first_name" headerName="First Name" cellClass="vertical-middle" />
          <AgGridColumn field="last_name" headerName="Last Name" cellClass="vertical-middle" />
          <AgGridColumn field="email" headerName="Email" cellClass="vertical-middle" />
          <AgGridColumn field="avatar" headerName="Avatar" cellRendererFramework={avatarFormatter} cellClass="vertical-middle" />
        </AgGridReact>
      </div>
    </div>
  );
}

export default App;
src/App.css
//src/App.css
.App {
  padding: 50px;
}
.ag-style {
  height: 280px;
  width: 100%;
}
.vertical-middle {
  display: flex;
  align-items: center;
}
.vertical-middle img {
  display: block;
  border: 1px solid #ddd;
  border-radius: 3px;
}

ReactJS How to Implement AG Grid

ReactJS How to Implement AG Grid

In this tutorial we will create a sample to load static data in a grid.

AG Grid is a fully-featured and highly customizable JavaScript data grid. It delivers outstanding performance, has no 3rd party dependencies and integrates smoothly with React as React Component.

Module not found: Can't resolve 'ag-grid-community/dist/styles/ag-grid.css'

C:\reactdev\myreactdev>npm install --save ag-grid-community

https://www.npmjs.com/package/ag-grid-community

Module not found: Can't resolve 'ag-grid-react' in 'C:\reactdev\myreactdev\src'
C:\reactdev\myreactdev>npm i --save ag-grid-community ag-grid-react react-dom-factories

https://www.npmjs.com/package/ag-grid-react

src/index.js
//src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
public/index.html
//public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>ReactJS </title>
  </head>
  <body>
    <div id="root"></div>
</body>
</html>
src/App.js
//src/App.js
import { AgGridColumn, AgGridReact } from 'ag-grid-react';

import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';

import './App.css';

const rowData = [
  {
    id: 1,
    email: "george.bluth@reqres.in",
    first_name: "George",
    last_name: "Bluth",
    avatar: "https://reqres.in/img/faces/1-image.jpg"
  },
  {
    id: 2,
    email: "janet.weaver@reqres.in",
    first_name: "Janet",
    last_name: "Weaver",
    avatar: "https://reqres.in/img/faces/2-image.jpg"
  },
  {
    id: 3,
    email: "emma.wong@reqres.in",
    first_name: "Emma",
    last_name: "Wong",
    avatar: "https://reqres.in/img/faces/3-image.jpg"
  },
  {
    id: 4,
    email: "eve.holt@reqres.in",
    first_name: "Eve",
    last_name: "Holt",
    avatar: "https://reqres.in/img/faces/4-image.jpg"
  },
  {
    id: 5,
    email: "charles.morris@reqres.in",
    first_name: "Charles",
    last_name: "Morris",
    avatar: "https://reqres.in/img/faces/5-image.jpg"
  },
  {
    id: 6,
    email: "tracey.ramos@reqres.in",
    first_name: "Tracey",
    last_name: "Ramos",
    avatar: "https://reqres.in/img/faces/6-image.jpg"
  },
  {
    id: 7,
    email: "michael.lawson@reqres.in",
    first_name: "Michael",
    last_name: "Lawson",
    avatar: "https://reqres.in/img/faces/7-image.jpg"
  },
  {
    id: 8,
    email: "lindsay.ferguson@reqres.in",
    first_name: "Lindsay",
    last_name: "Ferguson",
    avatar: "https://reqres.in/img/faces/8-image.jpg"
  },
  {
    id: 9,
    email: "tobias.funke@reqres.in",
    first_name: "Tobias",
    last_name: "Funke",
    avatar: "https://reqres.in/img/faces/9-image.jpg"
  },
  {
    id: 10,
    email: "byron.fields@reqres.in",
    first_name: "Byron",
    last_name: "Fields",
    avatar: "https://reqres.in/img/faces/10-image.jpg"
  },
  {
    id: 11,
    email: "george.edwards@reqres.in",
    first_name: "George",
    last_name: "Edwards",
    avatar: "https://reqres.in/img/faces/11-image.jpg"
  },
  {
    id: 12,
    email: "rachel.howell@reqres.in",
    first_name: "Rachel",
    last_name: "Howell",
    avatar: "https://reqres.in/img/faces/12-image.jpg"
  }
];

function App() {

  const avatarFormatter = ({ value }) => {
    return <img src={value} width="50px" height="50px" />
  }

  return (
    <div className="App">
      <h2>ReactJS How to Implement AG Grid</h2>
      <div className="ag-theme-alpine ag-style">
        <AgGridReact
          defaultColDef={{ flex: 1 }}
          rowHeight={60}
          rowData={rowData} >
          <AgGridColumn field="first_name" headerName="First Name" sortable={true} filter={true} cellClass="vertical-middle" />
          <AgGridColumn field="last_name" headerName="Last Name" sortable={true} filter={true} cellClass="vertical-middle" />
          <AgGridColumn field="email" headerName="Email" sortable={true} filter={true} cellClass="vertical-middle" />
          <AgGridColumn field="avatar" headerName="Avatar" sortable={true} filter={true} cellRendererFramework={avatarFormatter} cellClass="vertical-middle" />
        </AgGridReact>
      </div>
    </div>
  );
}

export default App;
src/App.css
//src/App.css
.App {
  padding: 50px;
}
.ag-style {
  height: 500px;
  width: 100%;
}
.vertical-middle {
  display: flex;
  align-items: center;
}
.vertical-middle img {
  display: block;
  border: 1px solid #ddd;
  border-radius: 3px;
}

Sunday, September 26, 2021

ReactJS Add Emoji Picker - emoji-picker-react

ReactJS Add Emoji Picker - emoji-picker-react

if you are working with a chatbot application this is how to add a Emoji using Emoji Picker

Install Emoji Picker
npm i emoji-picker-react
C:\reactdev\myreactdev>npm i emoji-picker-react

https://www.npmjs.com/package/emoji-picker-react
src/index.js
//src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
public/index.html
//public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>ReactJS </title>
  </head>
  <body>
    <div id="root"></div>
</body>
</html>
src/App.js
//src/App.js
import React, { useState } from 'react';
import Picker from 'emoji-picker-react';
import './App.css';

function App() {

  const [inputStr, setInputStr] = useState('');
  const [showPicker, setShowPicker] = useState(false);

  const onEmojiClick = (event, emojiObject) => {
    setInputStr(prevInput => prevInput + emojiObject.emoji);
    setShowPicker(false);
  };

  return (
    <div className="app">
      <h3>Add Emoji Picker</h3>
      <div className="picker-container">
        <input
          className="input-style"
          value={inputStr}
          onChange={e => setInputStr(e.target.value)} />
        <img
          className="emoji-icon"
          src="https://icons.getbootstrap.com/assets/icons/emoji-smile.svg"
          onClick={() => setShowPicker(val => !val)} />
        {showPicker && <Picker
          pickerStyle={{ width: '100%' }}
          onEmojiClick={onEmojiClick} />}
      </div>
    </div>
  );
}
export default App;
src/App.css
//src/App.css
.picker-container {
  position: relative;
  width: 300px;
}
.emoji-icon {
  cursor: pointer;
  position: absolute;
  top: 8px;
  right: 5px;
}
.input-style {
  padding: 7px 30px 7px 10px;
  width: calc(100% - 40px);
  border-radius: 3px;
  border: 1px solid #999;
  margin-bottom: 10px;
}

Saturday, September 25, 2021

ReactJS MultiSelect dropdown

ReactJS MultiSelect dropdown

Install react-select package

npm install react-select
C:\reactdev\myreactdev>npm install react-select

import Select from 'react-select';

src/index.js
//src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
public/index.html
//public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>ReactJS </title>
  </head>
  <body>
    <div id="root"></div>
</body>
</html>
src/App.js
//src/App.js
import React, { useState } from 'react';
import Select from 'react-select';

function App() {
  const data = [
    {
      value: 1,
      label: "Python"
    },
    {
      value: 2,
      label: "Swift"
    },
    {
      value: 3,
      label: "Javascript"
    },
    {
      value: 4,
      label: "PHP"
    },
    {
      value: 5,
      label: "C#"
    },
    {
      value: 6,
      label: "Go"
    }
  ];

  const [selectedOption, setSelectedOption] = useState(null);

  // handle onChange event of the dropdown
  const handleChange = e => {
    setSelectedOption(e);
  }

  return (
    <div className="App">
      <b>MultiSelect Dropdown</b><br />

      <Select
        isMulti
        placeholder="Select Option"
        value={selectedOption} 
        options={data} // list of the data
        onChange={handleChange} // assign onChange function
      />

      {selectedOption && <div style={{ marginTop: 20, lineHeight: '25px' }}>
        <b>Selected Options</b><br />
        <pre>{JSON.stringify(selectedOption, null, 2)}</pre>
      </div>}
    </div>
  );
}
export default App;

Friday, September 24, 2021

ReactJS Login Form with Bootstrap and Reactstrap

ReactJS Login Form with Bootstrap and Reactstrap

reactstrap Bootstrap 4 components that allow a great deal of flexibility and prebuilt validation https://reactstrap.github.io/

Install bootstrap
npm install bootstrap
C:\reactdev\myreactdev>npm install bootstrap

Install reactstrap
npm install reactstrap
C:\reactdev\myreactdev>npm install reactstrap

import bootstrap to src/index.js
import 'bootstrap/dist/css/bootstrap.min.css';


src/index.js
//src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import 'bootstrap/dist/css/bootstrap.min.css';

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
public/index.html
//public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>ReactJS </title>
  </head>
  <body>
    <div id="root"></div>
</body>
</html>
src/App.js
//src/App.js
import { Component } from 'react';
import {
  Form,
  FormFeedback,
  FormGroup,
  FormText,
  Label,
  Input,
  Button,
} from 'reactstrap';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: '',
      password: '',
      validate: {
        emailState: '',
      },
    };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange = (event) => {
    const { target } = event;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const { name } = target;

    this.setState({
      [name]: value,
    });
  };

  validateEmail(e) {
    const emailRex =
      /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

    const { validate } = this.state;

    if (emailRex.test(e.target.value)) {
      validate.emailState = 'has-success';
    } else {
      validate.emailState = 'has-danger';
    }

    this.setState({ validate });
  }

  submitForm(e) {
    e.preventDefault();
    console.log(`Email: ${this.state.email}`);
  }

  render() {
    const { email, password } = this.state;

    return (
      <div className="App">
        <h2>Sign In</h2>
        <Form className="form" onSubmit={(e) => this.submitForm(e)}>
          <FormGroup>
            <Label>Username</Label>
            <Input
              type="email"
              name="email"
              id="exampleEmail"
              placeholder="example@example.com"
              valid={this.state.validate.emailState === "has-success"}
              invalid={this.state.validate.emailState === "has-danger"}
              value={email}
              onChange={(e) => {
                this.validateEmail(e);
                this.handleChange(e);
              }}
            />
            <FormFeedback>
              Uh oh! Looks like there is an issue with your email. Please input
              a correct email.
            </FormFeedback>
            <FormFeedback valid>
              That's a tasty looking email you've got there.
            </FormFeedback>
            <FormText>Your username is most likely your email.</FormText>
          </FormGroup>
          <FormGroup>
            <Label for="examplePassword">Password</Label>
            <Input
              type="password"
              name="password"
              id="examplePassword"
              placeholder="********"
              value={password}
              onChange={(e) => this.handleChange(e)}
            />
          </FormGroup> <br/>
          <Button>Submit</Button>
        </Form>
      </div>
    );
  }
}

export default App;
src/App.css
//src/App.css
.App {
    border: 2px solid #d3d3d3;
    border-radius: .5em;
    margin-bottom: 1em;
    margin-left: auto;
    margin-right: auto;
    margin-top: 100px;
    padding: 1em;
    text-align: left;
    width: 600px;
  }
  
  .form {
    padding: 1em;
  }
  
  label {
    font-weight: 600;
  }

SwiftUI Simple TabView(PageTabView)

SwiftUI Simple TabView(PageTabView)
ContentView.swift
 
//
//  ContentView.swift
//  Swiftuitest
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    
    private var imageNames:[String] = ["1", "2","3","4","5","6","7"]
    var body: some View {
        
        TabView {
            TabView {
                ForEach(imageNames, id:\.self) {
                    imageNames in
                    
                    Image(imageNames)
                }
            }.tabViewStyle(PageTabViewStyle())
        }.frame(width: UIScreen.main.bounds.width - 20, height: 300, alignment: .center).cornerRadius(10)
    }
}

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

Thursday, September 23, 2021

How to fix Mac M1 Your CPU Does Not Support VT-x

How to fix Mac M1 Your CPU Does Not Support VT-x

Wednesday, September 22, 2021

How to install node.js on Mac and run nodejs hello program

How to install node.js on Mac and run nodejs hello program hello.js
const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Sunday, September 19, 2021

SwiftUI Firebase Fetching data from Firestore with SDWebImageSwiftUI and Details View

SwiftUI Firebase Fetching data from Firestore with SDWebImageSwiftUI and Details View

Login to fireabase and create database https://console.firebase.google.com/
SDWebImage https://github.com/SDWebImage/SDWebImageSwiftUI

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

import SwiftUI
import Firebase
import SDWebImageSwiftUI

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

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

struct Main : View {
  
  @ObservedObject var obser = observer()
  var body : some View{
      
        NavigationView {
            List(obser.users) { i in
                NavigationLink(destination : Details(userItem: i)) {
                    HStack {
                        AnimatedImage(url: URL(string: i.image)).resizable().frame(width: 60, height: 60).clipShape(Circle()).shadow(radius: 20)
                         
                        Text(i.name).padding(.leading, 10)
                    }
                }
            }.navigationBarTitle("Users")
        }
  }
}
datatypes.swift
 
//
//  datatypes.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import Foundation
import SwiftUI

struct datatype : Identifiable {
  
  var id : String
  var name : String
  var image : String
  var age : String
  var status : String
}
observer.swift
 
//
//  observer.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import Firebase

class observer : ObservableObject{
  
  @Published var users = [datatype]()
    
    init() {
        
        let db = Firestore.firestore()
        
        db.collection("users").getDocuments { (snap, err) in
            
            if err != nil{
                
                print((err?.localizedDescription)!)
                return
            }
            
            for i in snap!.documents{
                
                let name = i.get("name") as! String
                let age = i.get("age") as! String
                let image = i.get("image") as! String
                let id = i.documentID
                let status = i.get("status") as! String
                
                
                if status == ""{
                    
                self.users.append(datatype(id: id, name: name, image: image, age: age, status: status))
                    
                }

            }
        }
    }
}
Details.swift
 
//
//  Details.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import SDWebImageSwiftUI

struct Details: View {
    
    let userItem : datatype
    
    var body: some View {
        GeometryReader{geo in
            //Text(userItem.name)
            VStack {
                Text("Username : \(userItem.name)")
                    .font(.title2)
                 
                AnimatedImage(url: URL(string: userItem.image))
                    .resizable().frame(height: geo.size.height - 100)
                    .padding(.horizontal, 15)
                    .cornerRadius(20)
            }
        }
    }
}
DevSwiftUIApp.swift
 
//
//  DevSwiftUIApp.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import Firebase

@main
struct DevSwiftUIApp: App {

    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject,UIApplicationDelegate{
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        
        FirebaseApp.configure()
        return true
    }
}

How to create Admin Interfaces with React Admin and JSON Server Data For React-Admin

How to create Admin Interfaces with React Admin and JSON Server Data For React-Admin

react-admin A frontend Framework for building data-driven applications running in the browser on top of REST/GraphQL APIs, using ES6, React and Material Design. Previously named admin-on-rest. Open sourced and maintained by marmelab.

In this tutorial we will use react-admin to build an admin interface that uses the JSONPlaceholder API.

install the for react-admin:

npm install react-admin
C:\reactdev\myreactdev>npm install react-admin

https://github.com/marmelab/react-admin

Install ra-data-json-server

JSON Server Data Provider For React-Admin

npm install --save ra-data-json-server
C:\reactdev\myreactdev>npm install --save ra-data-json-server

https://www.npmjs.com/package/ra-data-json-server

JSON Server Data Provider for react-admin, the frontend framework for building admin applications on top of REST/GraphQL services.


https://jsonplaceholder.typicode.com/users
src/index.js
//src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
public/index.html
//public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>ReactJS </title>
  </head>
  <body>
    <div id="root"></div>
</body>
</html>
src/App.js
//src/App.js
import {
  Admin,
  Resource,
} from "react-admin";
import jsonServerProvider from 'ra-data-json-server';
import {
  UserList,
  UserEdit,
  UserCreate,
} from './Users';

const dataProvider = jsonServerProvider('https://jsonplaceholder.typicode.com');

function App() {
  return (
    <Admin dataProvider={dataProvider}>
      <Resource
        name="users"
        list={UserList}
        edit={UserEdit}
        create={UserCreate}
      />
    </Admin>
  );
}
export default App;
src/Users.js
//src/Users.js
import {
  List,
  Datagrid,
  TextField,
  EmailField,
  UrlField,
  Edit,
  SimpleForm,
  TextInput,
  Create,
} from 'react-admin';

export const UserList = props => (
  <List {...props}>
    <Datagrid rowClick="edit">
      <TextField source="id" />
      <TextField source="name" />
      <TextField source="username" />
      <EmailField source="email" />
      <TextField source="address.street" label="Address" />
      <TextField source="phone" />
      <UrlField source="website" />
      <TextField source="company.name" label="Company" />
    </Datagrid>
  </List>
);

export const UserEdit = props => (
  <Edit {...props}>
    <SimpleForm>
      <TextInput source="id" disabled />
      <TextInput source="name" />
      <TextInput source="username" />
      <TextInput source="email" />
      <TextInput source="address.street" label="Address" />
      <TextInput source="phone" />
      <TextInput source="website" />
      <TextInput source="company.name" label="Company" />
    </SimpleForm>
  </Edit>
);

export const UserCreate = props => (
  <Create {...props}>
    <SimpleForm>
      <TextInput source="name" />
      <TextInput source="username" />
      <TextInput source="email" />
      <TextInput source="address.street" label="Address" />
      <TextInput source="phone" />
      <TextInput source="website" />
      <TextInput source="company.name" label="Company" />
    </SimpleForm>
  </Create>
);

Friday, September 17, 2021

ReactJS Drag and Drop File Uploads using React Dropzone

ReactJS Drag and Drop File Uploads using React Dropzone

react-dropzone React component for handling the dragging and dropping of files. react-dropzone Simple React hook to create a HTML5-compliant drag'n'drop zone for files. Documentation and examples at https://react-dropzone.js.org. Source code at https://github.com/react-dropzone/react-dropzone/.
Install react-dropzone:
npm install --save react-dropzone

src/index.js
//src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
public/index.html
//public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>ReactJS </title>
  </head>
  <body>
    <div id="root"></div>
</body>
</html>
src/App.js
//src/App.js
import DropzoneComponent from './DropzoneComponent';

function App() {
  return (
    <div className="App">
      <DropzoneComponent />
    </div>
  );
}
export default App;
src/DropzoneComponent.js
//src/DropzoneComponent.js
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useDropzone } from 'react-dropzone';

const baseStyle = {
  display: 'flex',
  flexDirection: 'column',
  alignItems: 'center',
  padding: '20px',
  borderWidth: 2,
  borderRadius: 2,
  borderColor: '#eeeeee',
  borderStyle: 'dashed',
  backgroundColor: '#fafafa',
  color: '#bdbdbd',
  transition: 'border .3s ease-in-out'
};

const activeStyle = {
  borderColor: '#2196f3'
};

const acceptStyle = {
  borderColor: '#00e676'
};

const rejectStyle = {
  borderColor: '#ff1744'
};

function DropzoneComponent(props) {
  const [files, setFiles] = useState([]);
	
  const onDrop = useCallback(acceptedFiles => {
		setFiles(acceptedFiles.map(file => Object.assign(file, {
		  preview: URL.createObjectURL(file)
		})));
    console.log(acceptedFiles);
  }, []);

  const {
    getRootProps,
    getInputProps,
    isDragActive,
    isDragAccept,
    isDragReject
  } = useDropzone({
    onDrop,
    accept: 'image/jpeg, image/png'
  });

  const style = useMemo(() => ({
    ...baseStyle,
    ...(isDragActive ? activeStyle : {}),
    ...(isDragAccept ? acceptStyle : {}),
    ...(isDragReject ? rejectStyle : {})
  }), [
    isDragActive,
    isDragReject,
    isDragAccept
  ]);

  const thumbs = files.map(file => (
    <div key={file.name}>
      <img
        src={file.preview}
        alt={file.name}
      width="500" height="500"/>
    </div>
  ));

  // clean up
  useEffect(() => () => {
    files.forEach(file => URL.revokeObjectURL(file.preview));
  }, [files]);
  
  return (
    <section>
      <div {...getRootProps({style})}>
        <input {...getInputProps()} />
        <div>Drag and drop your images here.</div>
      </div>
      <aside>
        {thumbs}
      </aside>
    </section>
  )
}

export default DropzoneComponent;

Thursday, September 16, 2021

SwiftUI Simple Blog App

SwiftUI Simple Blog App

ContentView.swift
 
//
//  ContentView.swift
//  swiftuidev
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        
        TabView {
            MainView()
                .tabItem {
                    Image(systemName: "house.fill")
                    Text("Home")
                }
            AllPosts()
                .tabItem {
                    Image(systemName: "list.dash")
                    Text("See all")
                }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()  
    }
}
Creating the data model
BlogPosts.swift
 
//
//  BlogPosts.swift
//  swiftuidev
//
//  Created by Cairocoders
//

import Foundation

struct BlogPosts : Identifiable {
     
    var id : Int
    var name : String
    var image : String
    var details : String
}
 
var latestpost = [
 
    BlogPosts(id: 0, name: "Bistek Tagalog", image: "0", details: "A dish made of strips of salted and peppered sirloin beef, usually flattened with a meat tenderizing tool, slowly cooked in soy sauce, calamansi juice, garlic and onions, a specialty of the Tagalog region"),
    BlogPosts(id: 1, name: "Boogie flight", image: "1", details: "A boodle fight is a meal that dispenses with cutlery and dishes. Diners instead practice kamayan, Filipino for eating with the hands"),
    BlogPosts(id: 2, name: "Sinigang Na Baboy", image: "2", details: "Sinigang na baboy with Gabi is a Filipino pork soup with taro cooked in a sour broth."),
    BlogPosts(id: 3, name: "Ginisang Togue", image: "3", details: "Ginisang Togue is basically Sauteed Mung Bean Sprout with carrots, bell pepper, shrimp, and tofu."),
    BlogPosts(id: 4, name: "Ginisang Munggo (Monggo)", image: "4", details: "Munggo or Mung bean (or even green bean to some) is a seed of Vigna radiata, a plant native to India and Pakistan. Since the plant originated in Asia, it was easy to spread along the nearby countries. This seed became a hit when it reached the Philippines."),
    BlogPosts(id: 5, name: "Pork Estofado (Sweet Pork Stew)", image: "5", details: "Pork Estofado with saba bananas, carrots, Chinese sausage, and a sweet and savory sauce. Perfect with steamed rice!"),
    BlogPosts(id: 6, name: "Pata Tim", image: "6", details: "Brimming in a pork stew infused with aromatic peppercorn, sesame oil and soy sauce, Pata Tim is a classic Filipino dish with traces in Chinese cuisine"),
    BlogPosts(id: 7, name: "Pancit Palabok", image: "7", details: "Pancit Palabok is a noodle dish with shrimp sauce and topped with several ingredients such as cooked shrimp, boiled pork, crushed chicharon, tinapa flakes, fried tofu, scallions, and fried garlic. "),
]

var featuredpost = [
 
    BlogPosts(id: 0, name: "Adobong Manok", image: "0", details: "A dish made of strips of salted and peppered sirloin beef, usually flattened with a meat tenderizing tool, slowly cooked in soy sauce, calamansi juice, garlic and onions, a specialty of the Tagalog region"),
    BlogPosts(id: 1, name: "Boogie flight", image: "1", details: "A boodle fight is a meal that dispenses with cutlery and dishes. Diners instead practice kamayan, Filipino for eating with the hands"),
]
MainView.swift
 
//
//  MainView.swift
//  swiftuidev
//
//  Created by Cairocoders
//

import SwiftUI

struct MainView: View {
    
    var body: some View {
        
        NavigationView {
            ScrollView {
                // featured article
                VStack {
                    HStack {
                        Text("Featured posts")
                            .font(.title.bold())
                        Spacer()
                    }
                    LazyVStack {
                        ForEach(featuredpost){post in
                            //Text(store.name)
                            NavigationLink(destination: BlogPostView(blogPost: post)) {
                              BlogPostCardMain(blogPost: post)
                            }
                        }
                    }
                }
                .padding(.horizontal, 15)
                .padding(.vertical, 30)
                
                // latest articles
                VStack {
                    HStack {
                        Text("Latest posts")
                            .font(.title.bold())
                        Spacer()
                    }
                    .padding(.horizontal, 15)
                    
                    ScrollView(.horizontal, showsIndicators: false) {
                        LazyHStack(spacing: 15) {
                            
                            if latestpost.count >= 3 {
                                ForEach(latestpost[0...2]) { post in
                                    NavigationLink(destination: BlogPostView(blogPost: post)) {
                                        BlogPostCardMain(blogPost: post)
                                    }
                                }
                                
                            }else {
                                ForEach(latestpost[0..<latestpost.count]) { post in
                                    NavigationLink(destination: BlogPostView(blogPost: post)) {
                                        BlogPostCardMain(blogPost: post)
                                    }
                                }
                            }
                        }
                        .padding(.leading, 15)
                        .padding(.trailing, 30)
                    }
                    .frame(height: 420)
                    
                    Spacer()
                }
                .padding(.bottom, 40)
                
            }
            .navigationBarTitle("Home")
            .navigationBarItems(
                trailing: Button(action: {}) { Image(systemName: "arrow.clockwise.circle.fill")
                    .resizable()
                    .frame(width: 30, height: 30)
            })
        }
    }
}
BlogPostCardMain.swift
 
//
//  BlogPostCardMain.swift
//  swiftuidev
//
//  Created by Cairocoders
//

import SwiftUI

struct BlogPostCardMain: View {
    
    @Environment(\.colorScheme) var colorScheme
    var blogPost: BlogPosts
    
    var body: some View {
        VStack(alignment: .leading) {
            Image(blogPost.image)
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(height: 220)
                .frame(maxWidth: UIScreen.main.bounds.width - 80)
                .clipped()
                .clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
            VStack(spacing: 6) {
                HStack {
                    Text(blogPost.name)
                        .multilineTextAlignment(.leading)
                        .fixedSize(horizontal: false, vertical: true)
                        .lineLimit(3)
                        .font(Font.title2.bold())
                        .foregroundColor(.primary)
                    Spacer()
                }
                HStack {
                    Text(blogPost.details)
                        .multilineTextAlignment(.leading)
                        .fixedSize(horizontal: false, vertical: true)
                        .lineLimit(3)
                        .font(.subheadline)
                        .foregroundColor(.secondary)
                    Spacer()
                }
            }
            .frame(height: 110)
        }
        .padding(15)
        .background(colorScheme == .dark ? Color(hex: "#121212") : Color.white)
        .frame(maxWidth: UIScreen.main.bounds.width - 50, alignment: .leading)
        .clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
        .shadow(color: colorScheme == .dark ? .white.opacity(0.01) : .black.opacity(0.1), radius: 15, x: 0, y: 5)
    }
}

struct BlogPostCardMain_Previews: PreviewProvider {
    static var previews: some View {
        BlogPostCardMain(blogPost: BlogPosts(id: 1, name: "Adobo", image: "1", details: "sample"))
    }
}
AllPosts.swift
 
//
//  AllPosts.swift
//  swiftuidev
//
//  Created by Cairocoders
//

import SwiftUI

struct AllPosts: View {
    var body: some View {
        NavigationView {
            List {
                ForEach(latestpost) {post in
                    NavigationLink(destination: BlogPostView(blogPost: post)) {
                    BlogPostCardList(blogPost: post)
                    }
                }
            }
            .navigationTitle("All blog posts")
            .listStyle(InsetListStyle())
        }
    }
}

struct AllPosts_Previews: PreviewProvider {
    static var previews: some View {
        AllPosts()
    }
}
BlogPostCardList.swift
 
//
//  BlogPostCardList.swift
//  swiftuidev
//
//  Created by Cairocoders
//

import SwiftUI

struct BlogPostCardList: View {
    
    var blogPost: BlogPosts
    
    var body: some View {
        VStack(alignment: .leading) {
            Image(blogPost.image)
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(maxWidth: .infinity)
                .frame(height: 180)
                .frame(maxWidth: UIScreen.main.bounds.width - 60)
                .clipped()
                .clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
            VStack(spacing: 6) {
                HStack {
                    Text(blogPost.name)
                        .multilineTextAlignment(.leading)
                        .fixedSize(horizontal: false, vertical: true)
                        .lineLimit(3)
                        .font(Font.title2.bold())
                        .foregroundColor(.primary)
                    Spacer()
                }

                HStack {
                    Text(blogPost.details)
                        .multilineTextAlignment(.leading)
                        .fixedSize(horizontal: false, vertical: true)
                        .lineLimit(3)
                        .font(.subheadline)
                        .foregroundColor(.secondary)
                    Spacer()
                }
            }
        }
        .frame(maxWidth: UIScreen.main.bounds.width - 60, alignment: .leading)
        .padding()
    }
}

struct BlogPostCardList_Previews: PreviewProvider {
    static var previews: some View {
        BlogPostCardList(blogPost: BlogPosts(id: 1, name: "Adobo", image: "1", details: "Sample Details"))
    }
}
BlogPostView.swift
 
//
//  BlogPostView.swift
//  swiftuidev
//
//  Created by Cairocoders
//

import SwiftUI

struct BlogPostView: View {
    var blogPost: BlogPosts
    
    var body: some View {
        ZStack {
            ScrollView {
                VStack {
                    Image(blogPost.image)
                        .renderingMode(.original)
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(height: 310)
                        .frame(maxWidth: UIScreen.main.bounds.width)
                        .clipped()
                    
                    VStack {
                        HStack {
                            Text(blogPost.name)
                                .font(.title3)
                                .fontWeight(.heavy)
                                .foregroundColor(.primary)
                                .lineLimit(3)
                                .padding(.vertical, 15)
                            Spacer()
                        }
                        .frame(maxWidth: .infinity)
                        
                        Text(blogPost.details)
                            .multilineTextAlignment(.leading)
                            .font(.body)
                            .foregroundColor(Color.primary.opacity(0.9))
                            .padding(.bottom, 25)
                            .frame(maxWidth: .infinity)
                    }
                    .padding(.horizontal, 20)

                    Spacer()
                }
                .frame(maxWidth: .infinity)
                
            }
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}

struct BlogPostView_Previews: PreviewProvider {
    static var previews: some View {
        BlogPostView(blogPost: BlogPosts(id: 1, name: "Adobo", image: "1", details: "Sample Details"))
    }
}
HexColorExtension.swift
 
//
//  HexColorExtension.swift
//  swiftuidev
//
//  Created by Cairocoders
//

import Foundation
import SwiftUI

extension Color {
    init(hex: String) {
        let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
        var int: UInt64 = 0
        Scanner(string: hex).scanHexInt64(&int)
        let a, r, g, b: UInt64
        switch hex.count {
        case 3: // RGB (12-bit)
            (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
        case 6: // RGB (24-bit)
            (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
        case 8: // ARGB (32-bit)
            (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
        default:
            (a, r, g, b) = (1, 1, 1, 0)
        }

        self.init(
            .sRGB,
            red: Double(r) / 255,
            green: Double(g) / 255,
            blue:  Double(b) / 255,
            opacity: Double(a) / 255
        )
    }
}

Wednesday, September 15, 2021

SwiftUI Text Stroke Border

SwiftUI Text Stroke Border

In this tutorial I will show how to create a glowing border around SwiftUI text

ContentView.swift
//
//  ContentView.swift
//  swiftuidev
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        ZStack {
            Image("digitalart")
                .scaledToFill()
                .ignoresSafeArea()
            
            Text("Hello Cairocoders")
                .font(.largeTitle)
                .glowBorder(color: .pink, lineWidth: 6)
            
            Text("Text glowing border")
                .font(.largeTitle)
                .glowBorder(color: .orange, lineWidth: 10)
                .padding(.top, 190)
        }
    }
}

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


struct GlowBorder: ViewModifier {
    var color: Color
    var lineWidth: Int
    
    func body(content: Content) -> some View {
        applyShadow(content: AnyView(content), lineWidth: lineWidth)
    }
    
    func applyShadow(content: AnyView, lineWidth: Int) -> AnyView {
        if lineWidth == 0 {
            return content
        } else {
            return applyShadow(content: AnyView(content.shadow(color: color, radius: 1)), lineWidth: lineWidth - 1)
        }
    }
}

extension View {
    func glowBorder(color: Color, lineWidth: Int) -> some View {
        self.modifier(GlowBorder(color: color, lineWidth: lineWidth))
    }
}

Tuesday, September 14, 2021

SwiftUI Simple Youtube Design with Video Player AVKit

SwiftUI Simple Youtube Design with Video Player AVKit

 
//
//  ContentView.swift
//  swiftuidev
//
//  Created by Cairocoders
//

import SwiftUI
import AVKit

struct ContentView: View {
    
    var body: some View {
        GeometryReader { geo in
            ZStack {
                
                if UIDevice.current.orientation.isLandscape {
                    Color.black
                }
                
                VStack {
                    player().frame(height: UIDevice.current.orientation.isLandscape ? geo.size.height : geo.size.height / 3)
                        .edgesIgnoringSafeArea(.all)
                    
                    if !UIDevice.current.orientation.isLandscape {
                        Main()
                    }
                        
                        
                }
            }
        }
    }
}

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

struct player : UIViewControllerRepresentable {
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<player>) -> AVPlayerViewController {
        
        let player1 = AVPlayer(url: URL(string: "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/1080/Big_Buck_Bunny_1080_10s_1MB.mp4")!)
        
        let controller = AVPlayerViewController()
        controller.player = player1
        return controller
    }
    
    func updateUIViewController(_ uiViewController : AVPlayerViewController, context: UIViewControllerRepresentableContext<player>) {
        
        
    }
}

struct Main : View {
    var body: some View {
        
        ScrollView(.vertical, showsIndicators: false) {
            VStack {
                
                subscriber()
                
                ForEach(1..<5){i in
                    
                    VideoCard(image: "\(i)", name: "Pinoy Food Recipes \(i)")
                }
            }
        }.padding(10)
        

    }
}

struct subscriber : View {
    var body: some View {
        
        HStack {
            Image("photo1")
                .resizable()
                .clipShape(Circle())
                .frame(width: 50, height: 50)
            
            VStack (alignment: .leading, content: {
                Text("Cairocoders")
                    .fontWeight(.heavy).fixedSize()
                Text("5869 Subscribers")
                    .fixedSize()
            })
            
            Spacer()
            
            Button(action: {
                
            }) {
                Text("Subscribe").fontWeight(.heavy)
            }.foregroundColor(.red)
        }
    }
}

struct VideoCard : View {
    
    var image = ""
    var name = ""
    
    var body: some View {
        
        HStack {
            Image(image).resizable().frame(width: 120, height: 80)
            
            VStack(alignment: .leading, content: {
                Text(name).fontWeight(.heavy)
                Text("Cairocoders")
                Text("5689 View")
            }).frame(width: UIScreen.main.bounds.width - 170, alignment: .leading)
            
            VStack {
                Button(action: {
                    
                }) {
                    Image(systemName: "list.dash").resizable().frame(width: 15, height: 15).foregroundColor(.black)
                    Spacer()
                }.padding(.top, 5)
            }
        }
    }
}

Monday, September 13, 2021

SwiftUI View Portrait mode lock

SwiftUI View Portrait mode lock

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

import SwiftUI

struct ContentView: View {
    var body: some View {
        ZStack {
            NavigationView {
                VStack {
                    Text("View Portrait mode lock!")
                        .padding()
                    
                    HStack {
                        Image("photo1")
                            .resizable()
                    }
                    .frame(width: 250, height: 400)
                    .cornerRadius(20)
                }
                .navigationTitle("Portrait Mode")
                .navigationBarTitleDisplayMode(.inline)
            }
        }.onAppear {
            UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation") // Forcing the rotation to portrait
            AppDelegate.orientationLock = .portrait // And making sure it stays that way
        }.onDisappear {
            AppDelegate.orientationLock = .all // Unlocking the rotation when leaving the view
        }
    }
}

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

import SwiftUI

@main
struct TestApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate {
        
    static var orientationLock = UIInterfaceOrientationMask.all //By default you want all your views to rotate freely

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return AppDelegate.orientationLock
    }
}

Related Post