ContentView.swift
//
// ContentView.swift
// SwiftUITest
//
// Created by Cairocoders
//
import SwiftUI
struct ContentView: View {
@State private var search: String = ""
@State private var selectedIndex: Int = 1
private let categories = ["All", "Chair", "Sofa", "Sofabeds", "Mattresses", "Table"]
var body: some View {
NavigationView {
ZStack {
Color("Bg")
.ignoresSafeArea()
ScrollView (showsIndicators: false) {
VStack (alignment: .leading) {
AppBarView()
TagLineView()
.padding()
SearchAndScanView(search: $search)
ScrollView (.horizontal, showsIndicators: false) {
HStack {
ForEach(0 ..< categories.count) { i in
Button(action: {selectedIndex = i}) {
CategoryView(isActive: selectedIndex == i, text: categories[i])
}
}
}
.padding()
}
Text("Popular")
.font(.system(size: 24))
.padding(.horizontal)
ScrollView (.horizontal, showsIndicators: false) {
HStack (spacing: 0) {
ForEach(popular) { i in
NavigationLink(
destination: DetailScreen(viewmodel: i),
label: {
ProductCardView(image: Image(i.imageName), size: 210, title: i.title, rating: i.rating)
})
.navigationBarHidden(true)
.foregroundColor(.black)
}
.padding(.leading)
}
}
.padding(.bottom)
Text("Best")
.font(.system(size: 24))
.padding(.horizontal)
ScrollView (.horizontal, showsIndicators: false) {
HStack (spacing: 0) {
ForEach(best) { i in
ProductCardView(image: Image(i.imageName), size: 180, title: i.title, rating: i.rating)
}
.padding(.leading)
}
}
}
}
VStack {
Spacer()
BottomNavBarView()
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct BottomNavBarView: View {
var body: some View {
HStack {
BottomNavBarItem(image: Image(systemName: "house"), action: {})
BottomNavBarItem(image: Image(systemName: "suit.heart"), action: {})
BottomNavBarItem(image: Image(systemName: "cart"), action: {})
BottomNavBarItem(image: Image(systemName: "person"), action: {})
}
.padding()
.background(Color("Primary")).foregroundColor(Color.white)
.clipShape(Capsule())
.padding(.horizontal)
.shadow(color: Color.blue.opacity(0.15), radius: 8, x: 2, y: 6)
}
}
struct BottomNavBarItem: View {
let image: Image
let action: () -> Void
var body: some View {
Button(action: action) {
image
.frame(maxWidth: .infinity)
}
}
}
AppBarView.swift
//
// AppBarView.swift
// SwiftUITest
//
// Created by Cairocoders
//
import SwiftUI
struct AppBarView: View {
var body: some View {
HStack {
Button(action: {}) {
Image(systemName: "slider.horizontal.3")
.padding()
.background(Color.white)
.cornerRadius(10.0)
}
Spacer()
Button(action: {}) {
Image(uiImage: #imageLiteral(resourceName: "photo1"))
.resizable()
.frame(width: 42, height: 42)
.cornerRadius(10.0)
}
}
.padding(.horizontal)
}
}
struct AppBarView_Previews: PreviewProvider {
static var previews: some View {
AppBarView()
}
}
TagLineView.swift
//
// TagLineView.swift
// SwiftUITest
//
// Created by Cairocoders
//
import SwiftUI
struct TagLineView: View {
var body: some View {
Text("Shop \nBest ")
.font(.system(size: 28))
.foregroundColor(Color("Primary"))
+ Text("Furniture!")
.font(.system(size: 28))
.fontWeight(.bold)
.foregroundColor(Color("Primary"))
}
}
struct TagLineView_Previews: PreviewProvider {
static var previews: some View {
TagLineView()
}
}
SearchAndScanView.swift
//
// SearchAndScanView.swift
// SwiftUITest
//
// Created by Cairocoders
//
import SwiftUI
struct SearchAndScanView: View {
@Binding var search: String
var body: some View {
HStack {
HStack {
Image(systemName: "magnifyingglass")
.padding(.trailing, 8)
TextField("Search Furniture", text: $search)
}
.padding(.all, 20)
.background(Color.white)
.cornerRadius(10.0)
.padding(.trailing, 8)
Button(action: {}) {
Image(systemName: "text.magnifyingglass")
.padding().foregroundColor(Color.white)
.background(Color("Primary"))
.cornerRadius(10.0)
}
}
.padding(.horizontal)
}
}
struct SearchAndScanView_Previews: PreviewProvider {
@State static var search: String = ""
static var previews: some View {
SearchAndScanView(search: $search)
}
}
CategoryView.swift
//
// CategoryView.swift
// SwiftUITest
//
// Created by Cairocoders
//
import SwiftUI
struct CategoryView: View {
let isActive: Bool
let text: String
var body: some View {
VStack (alignment: .leading, spacing: 0) {
Text(text)
.font(.system(size: 18))
.fontWeight(.medium)
.foregroundColor(isActive ? Color("Primary") : Color.black.opacity(0.5))
if (isActive) { Color("Primary")
.frame(width: 15, height: 2)
.clipShape(Capsule())
}
}
.padding(.trailing)
}
}
ProductCardView.swift
//
// ProductCardView.swift
// SwiftUITest
//
// Created by Cairocoders
//
import SwiftUI
struct ProductCardView: View {
let image: Image
let size: CGFloat
let title: String
let rating: Int
var body: some View {
VStack {
image
.resizable()
.frame(width: size, height: 200 * (size/210))
.cornerRadius(20.0)
Text(title).font(.title3).fontWeight(.bold)
HStack (spacing: 2) {
ForEach(0..<rating) { rating in
Image(systemName: "star.fill")
.resizable()
.frame(width: 20, height: 20)
.foregroundColor(.yellow)
}
Spacer()
Text("$1299")
.font(.title3)
.fontWeight(.bold)
}
}
.frame(width: size)
.padding()
.background(Color.white)
.cornerRadius(20.0)
}
}
DetailScreen.swift
//
// DetailScreen.swift
// SwiftUITest
//
// Created by Cairocoders
//
import SwiftUI
struct DetailScreen: View {
let viewmodel: Furniture
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
ZStack {
Color("Bg")
ScrollView {
//Product Image
Image(viewmodel.imageName)
.resizable()
.aspectRatio(1,contentMode: .fit)
.edgesIgnoringSafeArea(.top)
DescriptionView(title: viewmodel.title, rating: viewmodel.rating)
}
.edgesIgnoringSafeArea(.top)
HStack {
Text("$1299")
.font(.title)
.foregroundColor(.white)
Spacer()
Text("Add to Cart")
.font(.title3)
.fontWeight(.semibold)
.foregroundColor(Color("Primary"))
.padding()
.padding(.horizontal, 8)
.background(Color.white)
.cornerRadius(10.0)
}
.padding()
.padding(.horizontal)
.background(Color("Primary"))
.cornerRadius(60.0, corners: .topLeft)
.frame(maxHeight: .infinity, alignment: .bottom)
.edgesIgnoringSafeArea(.bottom)
}
.navigationBarBackButtonHidden(true)
.navigationBarItems(leading: BackButton(action: {presentationMode.wrappedValue.dismiss()}), trailing: Image(systemName: "lineweight"))
}
}
struct RoundedCorner: Shape {
var radius: CGFloat = .infinity
var corners: UIRectCorner = .allCorners
func path(in rect: CGRect) -> Path {
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
return Path(path.cgPath)
}
}
extension View {
func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
clipShape( RoundedCorner(radius: radius, corners: corners) )
}
}
struct DetailScreen_Previews: PreviewProvider {
static var previews: some View {
DetailScreen(viewmodel: Furniture(id: 1, title: "Sofas", imageName: "1", rating: 5))
}
}
struct ColorDotView: View {
let color: Color
var body: some View {
color
.frame(width: 24, height: 24)
.clipShape(Circle())
}
}
struct DescriptionView: View {
let title : String
let rating : Int
@State var selected = -1
@State var message = false
@State private var count = 0
var body: some View {
VStack (alignment: .leading) {
// Title
Text(title)
.font(.title)
.fontWeight(.bold)
// Rating
HStack (spacing: 4) {
ForEach(0..<5) { rate in
Image(systemName: "star.fill")
.resizable()
.frame(width: 25, height: 25)
.foregroundColor(self.selected >= rate ? .yellow : .gray)
.onTapGesture {
self.selected = rate
self.message.toggle()
}
}
Text("(\(rating))")
.opacity(0.5)
.padding(.leading, 8)
Spacer()
}
.alert(isPresented: $message) {
Alert(title: Text("Rating Submit"), message: Text("You Rated \(self.selected + 1) out of 5 Star Rating"), dismissButton: .none)
}
Text("Description")
.fontWeight(.medium)
.padding(.vertical, 8)
Text("A Mid-Century Modern Modern dining chair with arm rest inspired by Eiffel chair made from polycarbonate plastic and has metal legs.")
.lineSpacing(8.0)
.opacity(0.6)
// Info
HStack (alignment: .top) {
VStack (alignment: .leading) {
Text("Size")
.font(.system(size: 16))
.fontWeight(.semibold)
Text("W53xD46.5xH83.5 cm")
.opacity(0.6)
}
}
.padding(.vertical)
// Colors and Counter
HStack {
VStack (alignment: .leading) {
Text("Colors")
.fontWeight(.semibold)
HStack {
ColorDotView(color: Color.red)
ColorDotView(color: Color.orange)
ColorDotView(color: Color.green)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
HStack {
// Minus Button
Button(action: {
stepCountminus()
}) {
Image(systemName: "minus")
.padding(.all, 8)
}
.frame(width: 30, height: 30)
.overlay(RoundedCorner(radius: 50).stroke())
.foregroundColor(.black)
Text("\(self.count)")
.font(.title2)
.fontWeight(.semibold)
.padding(.horizontal, 8)
// Plus Button
Button(action: {
stepCount()
}) {
Image(systemName: "plus")
.foregroundColor(.white)
.padding(.all, 8)
.background(Color("Primary"))
.clipShape(Circle())
}
}
}
}
.padding()
.padding(.top)
.background(Color("Bg"))
.cornerRadius(30, corners: [.topLeft, .topRight])
.offset(x: 0, y: -30.0)
}
func stepCount() {
count += 1
}
func stepCountminus() {
count -= 1
}
}
struct BackButton: View {
let action: () -> Void
var body: some View {
Button(action: action) {
Image(systemName: "chevron.backward")
.foregroundColor(.black)
.padding(.all, 12)
.background(Color.white)
.cornerRadius(8.0)
}
}
}
Model.swift
//
// Model.swift
// SwiftUITest
//
// Created by Cairocoders
//
import SwiftUI
struct Furniture : Identifiable {
var id : Int
var title : String
var imageName : String
var rating: Int
}
var popular = [Furniture(id: 0, title: "Pea Swivel Accent Chair", imageName: "1", rating: 4),
Furniture(id: 1, title: "Adelie Accent Chair", imageName: "2", rating: 3),
Furniture(id: 2, title: "Asha II Accent Chair", imageName: "3", rating: 5),
Furniture(id: 3, title: "Jenpeg Center Table", imageName: "4", rating: 4)]
var best = [Furniture(id: 0, title: "Cologne Sofabed", imageName: "5", rating: 3),
Furniture(id: 1, title: "Cleve Sofabed", imageName: "6", rating: 4),
Furniture(id: 2, title: "Cleve Sofabed", imageName: "7", rating: 5),
Furniture(id: 3, title: "Ivy Dining Chair", imageName: "4", rating: 2)]
