diff --git a/shop2.xcodeproj/project.pbxproj b/shop2.xcodeproj/project.pbxproj index 515a0225b403b0ee36defa559737e644ff4b030c..22d44492660bd6371c3f4c20a24fde3507a40829 100644 --- a/shop2.xcodeproj/project.pbxproj +++ b/shop2.xcodeproj/project.pbxproj @@ -13,6 +13,10 @@ 615AC3FC2C764237009924FB /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 615AC3FB2C764237009924FB /* Base */; }; 615AC3FE2C764238009924FB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 615AC3FD2C764238009924FB /* Assets.xcassets */; }; 615AC4012C764238009924FB /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 615AC4002C764238009924FB /* Base */; }; + 615AC40B2C764562009924FB /* productDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 615AC40A2C764562009924FB /* productDetails.swift */; }; + 615AC40F2C764721009924FB /* productAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 615AC40E2C764721009924FB /* productAPI.swift */; }; + 615AC4122C7663AD009924FB /* CustomTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 615AC4102C7663AD009924FB /* CustomTableViewCell.swift */; }; + 618005D72C76ED5B00E07B3E /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618005D62C76ED5B00E07B3E /* SecondViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -24,6 +28,10 @@ 615AC3FD2C764238009924FB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 615AC4002C764238009924FB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 615AC4022C764238009924FB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + 615AC40A2C764562009924FB /* productDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = productDetails.swift; sourceTree = "<group>"; }; + 615AC40E2C764721009924FB /* productAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = productAPI.swift; sourceTree = "<group>"; }; + 615AC4102C7663AD009924FB /* CustomTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTableViewCell.swift; sourceTree = "<group>"; }; + 618005D62C76ED5B00E07B3E /* SecondViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -56,10 +64,12 @@ 615AC3F32C764237009924FB /* shop2 */ = { isa = PBXGroup; children = ( + 618005DB2C770F6500E07B3E /* Controller */, + 618005DA2C770F5000E07B3E /* View */, + 618005D82C770F4000E07B3E /* Model */, 615AC3F42C764237009924FB /* AppDelegate.swift */, 615AC3F62C764237009924FB /* SceneDelegate.swift */, 615AC3F82C764237009924FB /* ViewController.swift */, - 615AC3FA2C764237009924FB /* Main.storyboard */, 615AC3FD2C764238009924FB /* Assets.xcassets */, 615AC3FF2C764238009924FB /* LaunchScreen.storyboard */, 615AC4022C764238009924FB /* Info.plist */, @@ -67,6 +77,40 @@ path = shop2; sourceTree = "<group>"; }; + 618005D82C770F4000E07B3E /* Model */ = { + isa = PBXGroup; + children = ( + 615AC40A2C764562009924FB /* productDetails.swift */, + ); + path = Model; + sourceTree = "<group>"; + }; + 618005DA2C770F5000E07B3E /* View */ = { + isa = PBXGroup; + children = ( + 615AC3FA2C764237009924FB /* Main.storyboard */, + ); + path = View; + sourceTree = "<group>"; + }; + 618005DB2C770F6500E07B3E /* Controller */ = { + isa = PBXGroup; + children = ( + 615AC4102C7663AD009924FB /* CustomTableViewCell.swift */, + 618005D62C76ED5B00E07B3E /* SecondViewController.swift */, + 618005DC2C770F7400E07B3E /* API */, + ); + path = Controller; + sourceTree = "<group>"; + }; + 618005DC2C770F7400E07B3E /* API */ = { + isa = PBXGroup; + children = ( + 615AC40E2C764721009924FB /* productAPI.swift */, + ); + path = API; + sourceTree = "<group>"; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -138,8 +182,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 615AC4122C7663AD009924FB /* CustomTableViewCell.swift in Sources */, + 615AC40F2C764721009924FB /* productAPI.swift in Sources */, 615AC3F92C764237009924FB /* ViewController.swift in Sources */, 615AC3F52C764237009924FB /* AppDelegate.swift in Sources */, + 618005D72C76ED5B00E07B3E /* SecondViewController.swift in Sources */, + 615AC40B2C764562009924FB /* productDetails.swift in Sources */, 615AC3F72C764237009924FB /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/shop2/Base.lproj/Main.storyboard b/shop2/Base.lproj/Main.storyboard deleted file mode 100644 index 25a763858ecdbea5c897a9fd8fa2225d7223d2ad..0000000000000000000000000000000000000000 --- a/shop2/Base.lproj/Main.storyboard +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> - <dependencies> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/> - <capability name="Safe area layout guides" minToolsVersion="9.0"/> - <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> - </dependencies> - <scenes> - <!--View Controller--> - <scene sceneID="tne-QT-ifu"> - <objects> - <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController"> - <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> - <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> - <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/> - </view> - </viewController> - <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> - </objects> - </scene> - </scenes> -</document> diff --git a/shop2/Controller/API/productAPI.swift b/shop2/Controller/API/productAPI.swift new file mode 100644 index 0000000000000000000000000000000000000000..bdf2296d162327528725f16a4f34673a23fd7798 --- /dev/null +++ b/shop2/Controller/API/productAPI.swift @@ -0,0 +1,24 @@ +// +// productAPI.swift +// shop2 +// +// Created by Jehu Ombrog on 8/22/24. +// + +import Foundation +class productController{ + + func fetchProductDetails() async throws -> [productDetails] { + let urlString = "https://fakestoreapi.com/products" + guard let url = URL(string:urlString) else { return [] } // to check that url must have value + + do{ + let (data , _) = try await URLSession.shared.data(from: url) + let productList = try JSONDecoder().decode([productDetails].self, from: data) + return productList + }catch{ + print("DEBUG: Error \(error.localizedDescription)") + return [] + } + } +} diff --git a/shop2/Controller/CustomTableViewCell.swift b/shop2/Controller/CustomTableViewCell.swift new file mode 100644 index 0000000000000000000000000000000000000000..73c7976b9ece2cdaaa02a5d6c14c516265e08ad2 --- /dev/null +++ b/shop2/Controller/CustomTableViewCell.swift @@ -0,0 +1,27 @@ +// +// CustomTableViewCell.swift +// shop2 +// +// Created by Jehu Ombrog on 8/22/24. +// + +import UIKit + +class CustomTableViewCell: UITableViewCell { + + @IBOutlet var productName : UILabel! + @IBOutlet var productPrice : UILabel! + @IBOutlet var producImage : UIImageView! + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + +} diff --git a/shop2/Controller/SecondViewController.swift b/shop2/Controller/SecondViewController.swift new file mode 100644 index 0000000000000000000000000000000000000000..8ce00653630265f357adc700cd46629ec2cad794 --- /dev/null +++ b/shop2/Controller/SecondViewController.swift @@ -0,0 +1,46 @@ +// +// SecondViewController.swift +// shop2 +// +// Created by Jehu Ombrog on 8/22/24. +// + +import UIKit + +class SecondViewController: UIViewController { + + @IBOutlet weak var productName : UILabel! + @IBOutlet weak var productPrice : UILabel! + @IBOutlet weak var productImage : UIImageView! + + var img : UIImage? { + didSet { + productImage.image = img + } + } + + var lblName = "" + var lblPrice = "" + + override func viewDidLoad() { + super.viewDidLoad() + + productName.text = lblName + productPrice.text = lblPrice + + + // Do any additional setup after loading the view. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/shop2/Model/productDetails.swift b/shop2/Model/productDetails.swift new file mode 100644 index 0000000000000000000000000000000000000000..bdb21c2c5d391b349d273b5855dec3598403cd2e --- /dev/null +++ b/shop2/Model/productDetails.swift @@ -0,0 +1,18 @@ +// +// productDetails.swift +// shop2 +// +// Created by Jehu Ombrog on 8/21/24. +// + +import Foundation + +struct productDetails: Codable, Identifiable{ + var id: Int + var title: String + var price: Double + var image: String + var description: String + var category: String + +} diff --git a/shop2/View/Base.lproj/Main.storyboard b/shop2/View/Base.lproj/Main.storyboard new file mode 100644 index 0000000000000000000000000000000000000000..32a8ac233c3209e8cf5626a1924cd7421c580bac --- /dev/null +++ b/shop2/View/Base.lproj/Main.storyboard @@ -0,0 +1,177 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="PNW-T3-Tjy"> + <device id="retina6_72" orientation="portrait" appearance="light"/> + <dependencies> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/> + <capability name="Safe area layout guides" minToolsVersion="9.0"/> + <capability name="System colors in document resources" minToolsVersion="11.0"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> + </dependencies> + <scenes> + <!--View Controller--> + <scene sceneID="tne-QT-ifu"> + <objects> + <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="shop2" customModuleProvider="target" sceneMemberID="viewController"> + <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> + <rect key="frame" x="0.0" y="0.0" width="430" height="932"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="mW4-X5-ZnP"> + <rect key="frame" x="0.0" y="103" width="430" height="795"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <prototypes> + <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="CustomTableViewCell" rowHeight="125" id="Uss-Jf-ehf" customClass="CustomTableViewCell" customModule="shop2" customModuleProvider="target"> + <rect key="frame" x="0.0" y="50" width="430" height="125"/> + <autoresizingMask key="autoresizingMask"/> + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Uss-Jf-ehf" id="xWa-T9-hUP"> + <rect key="frame" x="0.0" y="0.0" width="430" height="125"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="F25-4H-xyF"> + <rect key="frame" x="10" y="10" width="100" height="100"/> + <constraints> + <constraint firstAttribute="height" constant="100" id="3EM-sT-AS2"/> + <constraint firstAttribute="width" constant="100" id="CrH-7j-zQk"/> + </constraints> + </imageView> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ATq-0K-GJG"> + <rect key="frame" x="120" y="21" width="300" height="18"/> + <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="15"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gin-0N-e4L"> + <rect key="frame" x="320" y="84.666666666666671" width="80" height="19.333333333333329"/> + <color key="backgroundColor" systemColor="systemRedColor"/> + <constraints> + <constraint firstAttribute="width" constant="80" id="s9L-Si-uh9"/> + </constraints> + <fontDescription key="fontDescription" type="system" pointSize="16"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + </subviews> + <constraints> + <constraint firstAttribute="trailingMargin" secondItem="gin-0N-e4L" secondAttribute="trailing" constant="10" id="GE3-tZ-As2"/> + <constraint firstItem="F25-4H-xyF" firstAttribute="leading" secondItem="xWa-T9-hUP" secondAttribute="leading" constant="10" id="Vh6-o0-cmV"/> + <constraint firstItem="F25-4H-xyF" firstAttribute="top" secondItem="xWa-T9-hUP" secondAttribute="top" constant="10" id="aeY-LM-e86"/> + <constraint firstItem="ATq-0K-GJG" firstAttribute="top" secondItem="xWa-T9-hUP" secondAttribute="topMargin" constant="10" id="arj-Cx-ApM"/> + <constraint firstItem="ATq-0K-GJG" firstAttribute="leading" secondItem="F25-4H-xyF" secondAttribute="trailing" constant="10" id="qPL-xG-nF5"/> + <constraint firstAttribute="bottomMargin" secondItem="gin-0N-e4L" secondAttribute="bottom" constant="10" id="vhq-ao-bVP"/> + <constraint firstAttribute="trailing" secondItem="ATq-0K-GJG" secondAttribute="trailing" constant="10" id="wCZ-7y-mq0"/> + </constraints> + </tableViewCellContentView> + <connections> + <outlet property="producImage" destination="F25-4H-xyF" id="vA5-86-Wfy"/> + <outlet property="productName" destination="ATq-0K-GJG" id="bpn-7Y-R11"/> + <outlet property="productPrice" destination="gin-0N-e4L" id="vT6-OE-ioU"/> + </connections> + </tableViewCell> + </prototypes> + </tableView> + </subviews> + <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <constraints> + <constraint firstItem="mW4-X5-ZnP" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="8dH-8k-tLo"/> + <constraint firstItem="mW4-X5-ZnP" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="SXV-Wa-eQR"/> + <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="mW4-X5-ZnP" secondAttribute="trailing" id="tPN-eg-e3N"/> + <constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="mW4-X5-ZnP" secondAttribute="bottom" id="xGV-CX-fea"/> + </constraints> + </view> + <navigationItem key="navigationItem" id="p0V-K0-lme"/> + <connections> + <outlet property="tableView" destination="mW4-X5-ZnP" id="Vh3-ze-Qmc"/> + </connections> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="950.23255813953483" y="3.218884120171674"/> + </scene> + <!--Navigation Controller--> + <scene sceneID="XFv-7T-cec"> + <objects> + <navigationController automaticallyAdjustsScrollViewInsets="NO" id="PNW-T3-Tjy" sceneMemberID="viewController"> + <toolbarItems/> + <navigationBar key="navigationBar" contentMode="scaleToFill" id="GjD-HL-4I5"> + <rect key="frame" x="0.0" y="59" width="430" height="44"/> + <autoresizingMask key="autoresizingMask"/> + </navigationBar> + <nil name="viewControllers"/> + <connections> + <segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="7gK-FR-pSe"/> + </connections> + </navigationController> + <placeholder placeholderIdentifier="IBFirstResponder" id="Xg0-Mz-ERq" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="23.664122137404579" y="3.5211267605633805"/> + </scene> + <!--Product Details--> + <scene sceneID="k5b-nh-uZZ"> + <objects> + <viewController storyboardIdentifier="SecondViewController" id="TWg-l6-YWE" customClass="SecondViewController" customModule="shop2" customModuleProvider="target" sceneMemberID="viewController"> + <view key="view" contentMode="scaleToFill" id="GUj-Jp-Qny"> + <rect key="frame" x="0.0" y="0.0" width="430" height="932"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="9ZW-KG-i2N"> + <rect key="frame" x="115" y="213" width="200" height="200"/> + <constraints> + <constraint firstAttribute="width" constant="200" id="BQD-15-GMq"/> + <constraint firstAttribute="height" constant="200" id="PzM-aO-JLT"/> + </constraints> + </imageView> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Product Name" textAlignment="center" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="250" translatesAutoresizingMaskIntoConstraints="NO" id="RUe-aa-ICe"> + <rect key="frame" x="90" y="453.66666666666669" width="250" height="19.333333333333314"/> + <constraints> + <constraint firstAttribute="width" constant="250" id="b69-cb-NSX"/> + </constraints> + <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hls-Ox-2vm"> + <rect key="frame" x="175" y="502" width="80" height="21"/> + <color key="backgroundColor" systemColor="systemRedColor"/> + <constraints> + <constraint firstAttribute="width" constant="80" id="PpO-l2-pkX"/> + </constraints> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + </subviews> + <viewLayoutGuide key="safeArea" id="EgF-Md-b6Z"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <constraints> + <constraint firstItem="EgF-Md-b6Z" firstAttribute="trailing" secondItem="9ZW-KG-i2N" secondAttribute="trailing" constant="115" id="5n3-4T-7XX"/> + <constraint firstItem="hls-Ox-2vm" firstAttribute="centerX" secondItem="GUj-Jp-Qny" secondAttribute="centerX" id="HXZ-Hw-Wfr"/> + <constraint firstItem="EgF-Md-b6Z" firstAttribute="trailing" secondItem="RUe-aa-ICe" secondAttribute="trailing" constant="90" id="HZQ-ik-d18"/> + <constraint firstItem="RUe-aa-ICe" firstAttribute="leading" secondItem="EgF-Md-b6Z" secondAttribute="leading" constant="90" id="WEw-d5-53a"/> + <constraint firstItem="hls-Ox-2vm" firstAttribute="bottom" secondItem="RUe-aa-ICe" secondAttribute="bottom" constant="50" id="frt-WE-J3I"/> + <constraint firstItem="RUe-aa-ICe" firstAttribute="bottom" secondItem="9ZW-KG-i2N" secondAttribute="bottom" constant="60" id="hiz-LH-AQY"/> + <constraint firstItem="9ZW-KG-i2N" firstAttribute="leading" secondItem="EgF-Md-b6Z" secondAttribute="leading" constant="115" id="nXN-kU-F8n"/> + <constraint firstItem="9ZW-KG-i2N" firstAttribute="top" secondItem="EgF-Md-b6Z" secondAttribute="top" constant="154" id="tWJ-hf-UuI"/> + </constraints> + </view> + <navigationItem key="navigationItem" title="Product Details" id="UYF-xk-ybG"/> + <connections> + <outlet property="productImage" destination="9ZW-KG-i2N" id="sQM-q3-sJc"/> + <outlet property="productName" destination="RUe-aa-ICe" id="ljD-G4-RFa"/> + <outlet property="productPrice" destination="hls-Ox-2vm" id="dtZ-tR-NTY"/> + </connections> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="Jcc-TA-f9I" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="1707.9069767441861" y="3.8626609442060089"/> + </scene> + </scenes> + <resources> + <systemColor name="systemBackgroundColor"> + <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + </systemColor> + <systemColor name="systemRedColor"> + <color red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + </systemColor> + </resources> +</document> diff --git a/shop2/ViewController.swift b/shop2/ViewController.swift index 845f517e28500788de56e5e655781aaf29bb583d..974b37592db0b74efc997201997061af23c6f9f1 100644 --- a/shop2/ViewController.swift +++ b/shop2/ViewController.swift @@ -7,13 +7,114 @@ import UIKit -class ViewController: UIViewController { - +class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { + @IBOutlet var tableView : UITableView! + private let productService = productController() + var productList = [productDetails]() + override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view. - } + print("Table view:") + + + tableView.delegate = self + tableView.dataSource = self + + Task { + do { + try await fetchProducts() + } catch { + print("Failed to fetch products: \(error)") + } + } + } + + func fetchProducts() async throws { + do { + self.productList = try await productService.fetchProductDetails() + navigationItem.title = "Products" + + tableView.rowHeight = 120 + tableView.reloadData() + } catch { + print("Error fetching products: \(error)") + } + } + + private func loadImage(from url: URL, completion: @escaping (UIImage?) -> Void) { + let task = URLSession.shared.dataTask(with: url) { data, response, error in + if let error = error { + print("Error fetching image: \(error)") + completion(nil) + return + } + guard let data = data, let image = UIImage(data: data) else { + completion(nil) + return + } + completion(image) + } + task.resume() + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return productList.count + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if let vc = storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController{ + let product = productList[indexPath.row] + vc.lblName = product.title + vc.lblPrice = String(format: "$%.2f", product.price) + + if let imageUrl = URL(string: product.image) { + loadImage(from: imageUrl) { image in + DispatchQueue.main.async { + vc.img = image + print("DEBUG: image link \(product.image)") + print("DEBUG: UIImage \(image)") + } + } + } + + self .navigationController?.pushViewController(vc, animated: true) + } + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell + let product = productList[indexPath.row] + + if let imageUrl = URL(string: product.image) { + loadImage(from: imageUrl) { image in + DispatchQueue.main.async { + cell.producImage.image = image + } + } + } + + cell.productName.text = product.title + cell.productPrice.text = String(format: "$%.2f", product.price) + + + return cell + } + + } +extension UIImageView{ + func load(url: URL) { + DispatchQueue.global().async { [weak self] in + if let data = try? Data(contentsOf: url){ + if let image = UIImage(data: data) { + DispatchQueue.main.async { + self?.image = image + } + } + } + } + } +}