Toggle navigation
Toggle navigation
This project
Loading...
Sign in
open-source
/
warply_sdk_framework
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Network
Create a new issue
Commits
Issue Boards
Authored by
Manos Chorianopoulos
2026-03-02 17:51:21 +0200
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
825c7a6002e41f6a4b3891869c46e89735d8c934
825c7a60
1 parent
efab0210
add retrieveCoupon functionality
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
203 additions
and
55 deletions
SwiftWarplyFramework/Pods/Pods.xcodeproj/xcuserdata/manoschorianopoulos.xcuserdatad/xcschemes/xcschememanagement.plist
SwiftWarplyFramework/SwiftWarplyFramework.xcodeproj/xcuserdata/manoschorianopoulos.xcuserdatad/xcschemes/xcschememanagement.plist
SwiftWarplyFramework/SwiftWarplyFramework.xcworkspace/xcuserdata/manoschorianopoulos.xcuserdatad/UserInterfaceState.xcuserstate
SwiftWarplyFramework/SwiftWarplyFramework/Core/WarplySDK.swift
SwiftWarplyFramework/SwiftWarplyFramework/Network/Endpoints.swift
SwiftWarplyFramework/SwiftWarplyFramework/Network/NetworkService.swift
SwiftWarplyFramework/SwiftWarplyFramework/screens/CouponViewController/CouponViewController.xib
SwiftWarplyFramework/SwiftWarplyFramework/screens/CouponsetViewController/CouponsetViewController.swift
SwiftWarplyFramework/SwiftWarplyFramework/screens/CouponsetViewController/CouponsetViewController.xib
SwiftWarplyFramework/Pods/Pods.xcodeproj/xcuserdata/manoschorianopoulos.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
825c7a6
...
...
@@ -7,7 +7,7 @@
<key>
Pods-SwiftWarplyFramework.xcscheme_^#shared#^_
</key>
<dict>
<key>
orderHint
</key>
<integer>
1
</integer>
<integer>
0
</integer>
</dict>
</dict>
</dict>
...
...
SwiftWarplyFramework/SwiftWarplyFramework.xcodeproj/xcuserdata/manoschorianopoulos.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
825c7a6
...
...
@@ -7,7 +7,7 @@
<key>
SwiftWarplyFramework.xcscheme_^#shared#^_
</key>
<dict>
<key>
orderHint
</key>
<integer>
0
</integer>
<integer>
1
</integer>
</dict>
</dict>
</dict>
...
...
SwiftWarplyFramework/SwiftWarplyFramework.xcworkspace/xcuserdata/manoschorianopoulos.xcuserdatad/UserInterfaceState.xcuserstate
View file @
825c7a6
No preview for this file type
SwiftWarplyFramework/SwiftWarplyFramework/Core/WarplySDK.swift
View file @
825c7a6
...
...
@@ -1675,6 +1675,77 @@ public final class WarplySDK {
}
}
/// Retrieve a coupon from a coupon set (offer)
/// - Parameters:
/// - couponSetUuid: The UUID of the coupon set (offer) to retrieve a coupon from
/// - completion: Completion handler with response dictionary containing coupon code and expiration
/// - failureCallback: Failure callback with error code
///
/// Response structure on success:
/// ```json
/// {
/// "msg": "Retrieved",
/// "result": {
/// "coupon": "FNMRE2E5FXHH",
/// "expiration": "2026-10-31 23:59:00"
/// },
/// "status": 1
/// }
/// ```
public
func
retrieveCoupon
(
couponSetUuid
:
String
,
completion
:
@escaping
([
String
:
Any
]?)
->
Void
,
failureCallback
:
@escaping
(
Int
)
->
Void
)
{
Task
{
do
{
let
response
=
try
await
networkService
.
retrieveCoupon
(
couponSetUuid
:
couponSetUuid
)
await
MainActor
.
run
{
if
response
[
"status"
]
as?
Int
==
1
{
let
dynatraceEvent
=
LoyaltySDKDynatraceEventModel
()
dynatraceEvent
.
_eventName
=
"custom_success_retrieve_coupon_loyalty"
dynatraceEvent
.
_parameters
=
nil
self
.
postFrameworkEvent
(
"dynatrace"
,
sender
:
dynatraceEvent
)
print
(
"✅ [WarplySDK] Coupon retrieved successfully"
)
if
let
result
=
response
[
"result"
]
as?
[
String
:
Any
]
{
print
(
" Coupon:
\(
result
[
"coupon"
]
as?
String
??
"unknown"
)
"
)
print
(
" Expiration:
\(
result
[
"expiration"
]
as?
String
??
"unknown"
)
"
)
}
completion
(
response
)
}
else
{
let
dynatraceEvent
=
LoyaltySDKDynatraceEventModel
()
dynatraceEvent
.
_eventName
=
"custom_error_retrieve_coupon_loyalty"
dynatraceEvent
.
_parameters
=
nil
self
.
postFrameworkEvent
(
"dynatrace"
,
sender
:
dynatraceEvent
)
failureCallback
(
-
1
)
}
}
}
catch
{
await
MainActor
.
run
{
self
.
handleError
(
error
,
context
:
"retrieveCoupon"
,
endpoint
:
"retrieveCoupon"
,
failureCallback
:
failureCallback
)
}
}
}
}
/// Retrieve a coupon from a coupon set (async/await variant)
/// - Parameter couponSetUuid: The UUID of the coupon set (offer) to retrieve a coupon from
/// - Returns: Response dictionary containing coupon code and expiration
/// - Throws: WarplyError if the request fails
public
func
retrieveCoupon
(
couponSetUuid
:
String
)
async
throws
->
[
String
:
Any
]
{
return
try
await
withCheckedThrowingContinuation
{
continuation
in
retrieveCoupon
(
couponSetUuid
:
couponSetUuid
,
completion
:
{
response
in
if
let
response
=
response
{
continuation
.
resume
(
returning
:
response
)
}
else
{
continuation
.
resume
(
throwing
:
WarplyError
.
networkError
)
}
},
failureCallback
:
{
errorCode
in
continuation
.
resume
(
throwing
:
WarplyError
.
unknownError
(
errorCode
))
})
}
}
/// Verify ticket for user authentication
public
func
verifyTicket
(
guid
:
String
,
ticket
:
String
,
completion
:
@escaping
(
VerifyTicketResponseModel
?)
->
Void
)
{
// Clear previous state
...
...
SwiftWarplyFramework/SwiftWarplyFramework/Network/Endpoints.swift
View file @
825c7a6
...
...
@@ -89,6 +89,7 @@ public enum Endpoint {
// Coupon Operations
case
validateCoupon
(
coupon
:
[
String
:
Any
])
case
redeemCoupon
(
productId
:
String
,
productUuid
:
String
,
merchantId
:
String
)
case
retrieveCoupon
(
couponSetUuid
:
String
)
// Profile
case
getProfile
...
...
@@ -137,7 +138,7 @@ public enum Endpoint {
return
"/api/mobile/v2/{appUUID}/context/"
// Authenticated Context endpoints - /oauth/{appUUID}/context
case
.
getCampaignsPersonalized
,
.
getCoupons
,
.
getMarketPassDetails
,
.
getProfile
,
.
addCard
,
.
getCards
,
.
deleteCard
,
.
getTransactionHistory
,
.
getPointsHistory
,
.
validateCoupon
,
.
redeemCoupon
:
case
.
getCampaignsPersonalized
,
.
getCoupons
,
.
getMarketPassDetails
,
.
getProfile
,
.
addCard
,
.
getCards
,
.
deleteCard
,
.
getTransactionHistory
,
.
getPointsHistory
,
.
validateCoupon
,
.
redeemCoupon
,
.
retrieveCoupon
:
return
"/oauth/{appUUID}/context"
// Session endpoints - /api/session/{sessionUuid}
...
...
@@ -166,7 +167,7 @@ public enum Endpoint {
switch
self
{
case
.
register
,
.
changePassword
,
.
resetPassword
,
.
requestOtp
,
.
verifyTicket
,
.
refreshToken
,
.
logout
,
.
getCampaigns
,
.
getCampaignsPersonalized
,
.
getCoupons
,
.
getCouponSets
,
.
getAvailableCoupons
,
.
getMarketPassDetails
,
.
getProfile
,
.
addCard
,
.
getCards
,
.
deleteCard
,
.
getTransactionHistory
,
.
getPointsHistory
,
.
validateCoupon
,
.
redeemCoupon
,
.
getMerchants
,
.
getMerchantCategories
,
.
getArticles
,
.
sendEvent
,
.
sendDeviceInfo
,
.
getCosmoteUser
,
.
deiLogin
:
.
getMarketPassDetails
,
.
getProfile
,
.
addCard
,
.
getCards
,
.
deleteCard
,
.
getTransactionHistory
,
.
getPointsHistory
,
.
validateCoupon
,
.
redeemCoupon
,
.
retrieveCoupon
,
.
getMerchants
,
.
getMerchantCategories
,
.
getArticles
,
.
sendEvent
,
.
sendDeviceInfo
,
.
getCosmoteUser
,
.
deiLogin
:
return
.
POST
case
.
getSingleCampaign
,
.
getNetworkStatus
:
return
.
GET
...
...
@@ -383,6 +384,14 @@ public enum Endpoint {
]
]
case
.
retrieveCoupon
(
let
couponSetUuid
):
return
[
"coupon"
:
[
"action"
:
"retrieve_coupon"
,
"coupon_set"
:
couponSetUuid
]
]
// Merchants - using correct shops structure for DEI API
case
.
getMerchants
(
let
language
,
let
categories
,
let
defaultShown
,
let
center
,
let
tags
,
let
uuid
,
let
distance
,
let
parentUuids
):
return
[
...
...
@@ -473,7 +482,7 @@ public enum Endpoint {
return
.
standardContext
// Authenticated Context - /oauth/{appUUID}/context
case
.
getCampaignsPersonalized
,
.
getCoupons
,
.
getMarketPassDetails
,
.
getProfile
,
.
addCard
,
.
getCards
,
.
deleteCard
,
.
getTransactionHistory
,
.
getPointsHistory
,
.
validateCoupon
,
.
redeemCoupon
:
case
.
getCampaignsPersonalized
,
.
getCoupons
,
.
getMarketPassDetails
,
.
getProfile
,
.
addCard
,
.
getCards
,
.
deleteCard
,
.
getTransactionHistory
,
.
getPointsHistory
,
.
validateCoupon
,
.
redeemCoupon
,
.
retrieveCoupon
:
return
.
authenticatedContext
// Authentication - /oauth/{appUUID}/login, /oauth/{appUUID}/token
...
...
@@ -515,7 +524,7 @@ public enum Endpoint {
return
.
standard
// Bearer Token Authentication (loyalty headers + Authorization: Bearer)
case
.
changePassword
,
.
getCampaignsPersonalized
,
.
getCoupons
,
.
getMarketPassDetails
,
.
getProfile
,
.
addCard
,
.
getCards
,
.
deleteCard
,
.
getTransactionHistory
,
.
getPointsHistory
,
.
validateCoupon
,
.
redeemCoupon
:
case
.
changePassword
,
.
getCampaignsPersonalized
,
.
getCoupons
,
.
getMarketPassDetails
,
.
getProfile
,
.
addCard
,
.
getCards
,
.
deleteCard
,
.
getTransactionHistory
,
.
getPointsHistory
,
.
validateCoupon
,
.
redeemCoupon
,
.
retrieveCoupon
:
return
.
bearerToken
// Basic Authentication (loyalty headers + Authorization: Basic)
...
...
SwiftWarplyFramework/SwiftWarplyFramework/Network/NetworkService.swift
View file @
825c7a6
...
...
@@ -1084,6 +1084,20 @@ extension NetworkService {
return
response
}
/// Retrieve a coupon from a coupon set
/// - Parameter couponSetUuid: The UUID of the coupon set (offer) to retrieve a coupon from
/// - Returns: Response dictionary containing the retrieved coupon code and expiration
/// - Throws: NetworkError if request fails
public
func
retrieveCoupon
(
couponSetUuid
:
String
)
async
throws
->
[
String
:
Any
]
{
print
(
"🔄 [NetworkService] Retrieving coupon for coupon set:
\(
couponSetUuid
)
"
)
let
endpoint
=
Endpoint
.
retrieveCoupon
(
couponSetUuid
:
couponSetUuid
)
let
response
=
try
await
requestRaw
(
endpoint
)
print
(
"✅ [NetworkService] Coupon retrieval request completed"
)
return
response
}
// MARK: - Card Security Utilities
/// Mask card number for secure logging
...
...
SwiftWarplyFramework/SwiftWarplyFramework/screens/CouponViewController/CouponViewController.xib
View file @
825c7a6
<?xml version="1.0" encoding="UTF-8"?>
<document
type=
"com.apple.InterfaceBuilder3.CocoaTouch.XIB"
version=
"3.0"
toolsVersion=
"2
3094
"
targetRuntime=
"iOS.CocoaTouch"
propertyAccessControl=
"none"
useAutolayout=
"YES"
useTraitCollections=
"YES"
useSafeAreas=
"YES"
colorMatched=
"YES"
>
<document
type=
"com.apple.InterfaceBuilder3.CocoaTouch.XIB"
version=
"3.0"
toolsVersion=
"2
4506
"
targetRuntime=
"iOS.CocoaTouch"
propertyAccessControl=
"none"
useAutolayout=
"YES"
useTraitCollections=
"YES"
useSafeAreas=
"YES"
colorMatched=
"YES"
>
<device
id=
"retina6_12"
orientation=
"portrait"
appearance=
"light"
/>
<dependencies>
<plugIn
identifier=
"com.apple.InterfaceBuilder.IBCocoaTouchPlugin"
version=
"2
308
4"
/>
<plugIn
identifier=
"com.apple.InterfaceBuilder.IBCocoaTouchPlugin"
version=
"2
450
4"
/>
<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"
/>
...
...
@@ -55,10 +55,10 @@
<autoresizingMask
key=
"autoresizingMask"
widthSizable=
"YES"
heightSizable=
"YES"
/>
<subviews>
<view
contentMode=
"scaleToFill"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"XaT-fU-eNh"
userLabel=
"Main View"
>
<rect
key=
"frame"
x=
"0.0"
y=
"
59"
width=
"393"
height=
"793
"
/>
<rect
key=
"frame"
x=
"0.0"
y=
"
118"
width=
"393"
height=
"734
"
/>
<subviews>
<scrollView
clipsSubviews=
"YES"
multipleTouchEnabled=
"YES"
contentMode=
"scaleToFill"
showsHorizontalScrollIndicator=
"NO"
showsVerticalScrollIndicator=
"NO"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"YpC-uS-mhw"
>
<rect
key=
"frame"
x=
"0.0"
y=
"0.0"
width=
"393"
height=
"7
93
"
/>
<rect
key=
"frame"
x=
"0.0"
y=
"0.0"
width=
"393"
height=
"7
34
"
/>
<subviews>
<view
contentMode=
"scaleToFill"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"qrm-40-JLT"
userLabel=
"Scroll Content View"
>
<rect
key=
"frame"
x=
"0.0"
y=
"0.0"
width=
"393"
height=
"1177"
/>
...
...
@@ -74,14 +74,14 @@
<rect
key=
"frame"
x=
"239"
y=
"17"
width=
"138"
height=
"20.666666666666671"
/>
<subviews>
<imageView
clipsSubviews=
"YES"
userInteractionEnabled=
"NO"
contentMode=
"scaleAspectFit"
horizontalHuggingPriority=
"251"
verticalHuggingPriority=
"251"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"tFA-1H-T5S"
userLabel=
"Info Image View"
>
<rect
key=
"frame"
x=
"10"
y=
"3.6666666666666
723
"
width=
"13.666666666666664"
height=
"13.333333333333336"
/>
<rect
key=
"frame"
x=
"10"
y=
"3.6666666666666
581
"
width=
"13.666666666666664"
height=
"13.333333333333336"
/>
<constraints>
<constraint
firstAttribute=
"height"
constant=
"13.5"
id=
"uQt-vY-kbk"
/>
<constraint
firstAttribute=
"width"
constant=
"13.5"
id=
"yzR-99-6Vp"
/>
</constraints>
</imageView>
<label
opaque=
"NO"
userInteractionEnabled=
"NO"
contentMode=
"left"
horizontalHuggingPriority=
"251"
verticalHuggingPriority=
"251"
text=
"Περισσότερα"
textAlignment=
"natural"
lineBreakMode=
"tailTruncation"
baselineAdjustment=
"alignBaselines"
adjustsFontSizeToFit=
"NO"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"K34-LM-bC1"
userLabel=
"Info Label"
>
<rect
key=
"frame"
x=
"28"
y=
"-0.3333333333333
286
"
width=
"100"
height=
"21"
/>
<rect
key=
"frame"
x=
"28"
y=
"-0.3333333333333
4281
"
width=
"100"
height=
"21"
/>
<fontDescription
key=
"fontDescription"
type=
"system"
pointSize=
"17"
/>
<nil
key=
"textColor"
/>
<nil
key=
"highlightedColor"
/>
...
...
@@ -144,7 +144,7 @@
<rect
key=
"frame"
x=
"0.0"
y=
"0.0"
width=
"345"
height=
"54.333333333333336"
/>
<subviews>
<label
opaque=
"NO"
userInteractionEnabled=
"NO"
contentMode=
"left"
horizontalHuggingPriority=
"251"
verticalHuggingPriority=
"251"
text=
"Label"
lineBreakMode=
"tailTruncation"
baselineAdjustment=
"alignBaselines"
adjustsFontSizeToFit=
"NO"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"lEF-bh-hOi"
userLabel=
"CouponCodeTitleLabel"
>
<rect
key=
"frame"
x=
"17"
y=
"17"
width=
"277"
height=
"20.333333333333329"
/>
<rect
key=
"frame"
x=
"17"
y=
"17
.000000000000057
"
width=
"277"
height=
"20.333333333333329"
/>
<fontDescription
key=
"fontDescription"
type=
"system"
pointSize=
"17"
/>
<nil
key=
"textColor"
/>
<nil
key=
"highlightedColor"
/>
...
...
@@ -181,16 +181,16 @@
</constraints>
</view>
<view
contentMode=
"scaleToFill"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"wT1-HY-mg9"
userLabel=
"CouponCodeContentView"
>
<rect
key=
"frame"
x=
"0.0"
y=
"54.3333333333333
71
"
width=
"345"
height=
"80"
/>
<rect
key=
"frame"
x=
"0.0"
y=
"54.3333333333333
14
"
width=
"345"
height=
"80"
/>
<subviews>
<label
opaque=
"NO"
userInteractionEnabled=
"NO"
contentMode=
"left"
horizontalHuggingPriority=
"251"
verticalHuggingPriority=
"251"
text=
"Label"
lineBreakMode=
"tailTruncation"
baselineAdjustment=
"alignBaselines"
adjustsFontSizeToFit=
"NO"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"2Fn-5d-j8v"
userLabel=
"CouponCodeValueLabel"
>
<rect
key=
"frame"
x=
"16.999999999999996"
y=
"2
5.999999999999943
"
width=
"56.666666666666657"
height=
"28"
/>
<rect
key=
"frame"
x=
"16.999999999999996"
y=
"2
6
"
width=
"56.666666666666657"
height=
"28"
/>
<fontDescription
key=
"fontDescription"
type=
"system"
pointSize=
"24"
/>
<nil
key=
"textColor"
/>
<nil
key=
"highlightedColor"
/>
</label>
<imageView
clipsSubviews=
"YES"
userInteractionEnabled=
"NO"
contentMode=
"scaleAspectFit"
horizontalHuggingPriority=
"251"
verticalHuggingPriority=
"251"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"AXc-Yh-5Ek"
userLabel=
"CopyButtonImage"
>
<rect
key=
"frame"
x=
"84.666666666666671"
y=
"23.666666666666
686
"
width=
"33"
height=
"33"
/>
<rect
key=
"frame"
x=
"84.666666666666671"
y=
"23.666666666666
742
"
width=
"33"
height=
"33"
/>
<color
key=
"backgroundColor"
white=
"0.0"
alpha=
"0.0"
colorSpace=
"custom"
customColorSpace=
"genericGamma22GrayColorSpace"
/>
<constraints>
<constraint
firstAttribute=
"height"
constant=
"33"
id=
"7ds-Ao-fBn"
/>
...
...
@@ -318,7 +318,7 @@
<nil
key=
"highlightedColor"
/>
</label>
<imageView
clipsSubviews=
"YES"
userInteractionEnabled=
"NO"
contentMode=
"scaleAspectFit"
horizontalHuggingPriority=
"251"
verticalHuggingPriority=
"251"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"C8k-TU-LiL"
userLabel=
"TermsButtonArrowImage"
>
<rect
key=
"frame"
x=
"109.33333333333334"
y=
"15"
width=
"9"
height=
"5"
/>
<rect
key=
"frame"
x=
"109.33333333333334"
y=
"15
.000000000000114
"
width=
"9"
height=
"5"
/>
<color
key=
"backgroundColor"
white=
"0.0"
alpha=
"0.0"
colorSpace=
"custom"
customColorSpace=
"genericGamma22GrayColorSpace"
/>
<constraints>
<constraint
firstAttribute=
"height"
constant=
"5"
id=
"ERb-FD-j0Y"
/>
...
...
@@ -349,7 +349,7 @@
</constraints>
</view>
<label
opaque=
"NO"
userInteractionEnabled=
"NO"
contentMode=
"left"
horizontalHuggingPriority=
"251"
verticalHuggingPriority=
"251"
text=
"Label"
lineBreakMode=
"tailTruncation"
numberOfLines=
"0"
baselineAdjustment=
"alignBaselines"
adjustsFontSizeToFit=
"NO"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"Ak8-Tc-k8X"
userLabel=
"TermsLabel"
>
<rect
key=
"frame"
x=
"24"
y=
"940.666666666666
63
"
width=
"345"
height=
"20.333333333333371"
/>
<rect
key=
"frame"
x=
"24"
y=
"940.666666666666
74
"
width=
"345"
height=
"20.333333333333371"
/>
<constraints>
<constraint
firstAttribute=
"height"
constant=
"20.329999999999998"
id=
"ZA1-TX-m9Y"
/>
</constraints>
...
...
SwiftWarplyFramework/SwiftWarplyFramework/screens/CouponsetViewController/CouponsetViewController.swift
View file @
825c7a6
...
...
@@ -42,9 +42,7 @@ import UIKit
@IBOutlet
weak
var
termsLabel
:
UILabel
!
@IBOutlet
weak
var
termsLabelHeight
:
NSLayoutConstraint
!
@IBOutlet
weak
var
mapButton
:
UIButton
!
@IBOutlet
weak
var
websiteButton
:
UIButton
!
@IBOutlet
weak
var
redeemButton
:
UIButton
!
var
couponset
:
CouponSetItemModel
?
private
var
isDetailsExpanded
=
false
...
...
@@ -52,6 +50,9 @@ import UIKit
private
var
isCouponQRExpanded
=
false
private
var
isTermsExpanded
=
false
// Loader overlay
private
var
loaderOverlay
:
UIView
?
var
postImageURL
:
String
?
{
didSet
{
if
let
url
=
postImageURL
{
...
...
@@ -97,21 +98,13 @@ import UIKit
termsButton
.
addTarget
(
self
,
action
:
#selector(
toggleTerms
)
,
for
:
.
touchUpInside
)
termsLabelHeight
.
constant
=
0
mapButton
.
titleLabel
?
.
font
=
UIFont
(
name
:
"PingLCG-Bold"
,
size
:
16
)
mapButton
.
setTitle
(
"Καταστήματα κοντά μου"
,
for
:
.
normal
)
mapButton
.
setTitleColor
(
UIColor
(
rgb
:
0xFFFFFF
),
for
:
.
normal
)
mapButton
.
setTitleColor
(
UIColor
(
rgb
:
0xFFFFFF
),
for
:
.
highlighted
)
mapButton
.
layer
.
cornerRadius
=
4.0
mapButton
.
backgroundColor
=
UIColor
(
rgb
:
0x000F1E
)
websiteButton
.
titleLabel
?
.
font
=
UIFont
(
name
:
"PingLCG-Bold"
,
size
:
16
)
websiteButton
.
setTitle
(
"Δες το website"
,
for
:
.
normal
)
websiteButton
.
setTitleColor
(
UIColor
(
rgb
:
0x000F1E
),
for
:
.
normal
)
websiteButton
.
setTitleColor
(
UIColor
(
rgb
:
0x000F1E
),
for
:
.
highlighted
)
websiteButton
.
backgroundColor
=
.
clear
websiteButton
.
layer
.
borderWidth
=
1
websiteButton
.
layer
.
borderColor
=
UIColor
(
rgb
:
0x000F1E
)
.
cgColor
websiteButton
.
layer
.
cornerRadius
=
4.0
redeemButton
.
titleLabel
?
.
font
=
UIFont
(
name
:
"PingLCG-Bold"
,
size
:
16
)
redeemButton
.
setTitle
(
"Απόκτησε το κουπόνι"
,
for
:
.
normal
)
redeemButton
.
setTitleColor
(
UIColor
(
rgb
:
0xFFFFFF
),
for
:
.
normal
)
redeemButton
.
setTitleColor
(
UIColor
(
rgb
:
0xFFFFFF
),
for
:
.
highlighted
)
redeemButton
.
layer
.
cornerRadius
=
4.0
redeemButton
.
backgroundColor
=
UIColor
(
rgb
:
0x000F1E
)
redeemButton
.
addTarget
(
self
,
action
:
#selector(
redeemButtonTapped
)
,
for
:
.
touchUpInside
)
// Configure the view with offer data
if
let
offer
=
couponset
{
...
...
@@ -119,6 +112,79 @@ import UIKit
}
}
@objc
private
func
redeemButtonTapped
()
{
guard
let
couponSetUuid
=
couponset
?
.
_uuid
,
!
couponSetUuid
.
isEmpty
else
{
showErrorAlert
(
message
:
"Δεν βρέθηκε το αναγνωριστικό της προσφοράς."
)
return
}
// Disable button to prevent double taps
redeemButton
.
isEnabled
=
false
showLoader
()
WarplySDK
.
shared
.
retrieveCoupon
(
couponSetUuid
:
couponSetUuid
,
completion
:
{
[
weak
self
]
response
in
guard
let
self
=
self
else
{
return
}
self
.
hideLoader
()
self
.
redeemButton
.
isEnabled
=
true
if
let
response
=
response
,
let
result
=
response
[
"result"
]
as?
[
String
:
Any
],
let
couponCode
=
result
[
"coupon"
]
as?
String
{
let
expiration
=
result
[
"expiration"
]
as?
String
??
""
self
.
showSuccessAlert
(
couponCode
:
couponCode
,
expiration
:
expiration
)
}
else
{
self
.
showErrorAlert
(
message
:
"Η ενεργοποίηση του κουπονιού απέτυχε. Παρακαλώ δοκίμασε ξανά."
)
}
},
failureCallback
:
{
[
weak
self
]
errorCode
in
guard
let
self
=
self
else
{
return
}
self
.
hideLoader
()
self
.
redeemButton
.
isEnabled
=
true
self
.
showErrorAlert
(
message
:
"Η ενεργοποίηση του κουπονιού απέτυχε. Παρακαλώ δοκίμασε ξανά."
)
})
}
// MARK: - Loader
private
func
showLoader
()
{
let
overlay
=
UIView
(
frame
:
self
.
view
.
bounds
)
overlay
.
backgroundColor
=
UIColor
.
black
.
withAlphaComponent
(
0.3
)
overlay
.
autoresizingMask
=
[
.
flexibleWidth
,
.
flexibleHeight
]
let
spinner
=
UIActivityIndicatorView
(
style
:
.
large
)
spinner
.
color
=
.
white
spinner
.
center
=
overlay
.
center
spinner
.
autoresizingMask
=
[
.
flexibleTopMargin
,
.
flexibleBottomMargin
,
.
flexibleLeftMargin
,
.
flexibleRightMargin
]
spinner
.
startAnimating
()
overlay
.
addSubview
(
spinner
)
self
.
view
.
addSubview
(
overlay
)
self
.
loaderOverlay
=
overlay
}
private
func
hideLoader
()
{
loaderOverlay
?
.
removeFromSuperview
()
loaderOverlay
=
nil
}
// MARK: - Alerts
private
func
showSuccessAlert
(
couponCode
:
String
,
expiration
:
String
)
{
var
message
=
"Ο κωδικός κουπονιού σου:
\n\(
couponCode
)
"
if
!
expiration
.
isEmpty
{
message
+=
"
\n\n
Λήξη:
\(
expiration
)
"
}
let
alert
=
UIAlertController
(
title
:
"Επιτυχία"
,
message
:
message
,
preferredStyle
:
.
alert
)
alert
.
addAction
(
UIAlertAction
(
title
:
"OK"
,
style
:
.
default
,
handler
:
nil
))
present
(
alert
,
animated
:
true
,
completion
:
nil
)
}
private
func
showErrorAlert
(
message
:
String
)
{
let
alert
=
UIAlertController
(
title
:
"Σφάλμα"
,
message
:
message
,
preferredStyle
:
.
alert
)
alert
.
addAction
(
UIAlertAction
(
title
:
"OK"
,
style
:
.
default
,
handler
:
nil
))
present
(
alert
,
animated
:
true
,
completion
:
nil
)
}
private
func
setupUI
(
with
couponset
:
CouponSetItemModel
)
{
// couponImage.image = UIImage(named: couponset._img_preview, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
self
.
postImageURL
=
couponset
.
_img_preview
...
...
SwiftWarplyFramework/SwiftWarplyFramework/screens/CouponsetViewController/CouponsetViewController.xib
View file @
825c7a6
...
...
@@ -17,7 +17,7 @@
<outlet
property=
"infoImage"
destination=
"RK8-R9-SZK"
id=
"ZjM-PX-DgT"
/>
<outlet
property=
"infoLabel"
destination=
"oln-Zl-Mu1"
id=
"OZb-dV-dlF"
/>
<outlet
property=
"infoView"
destination=
"raJ-sJ-NGX"
id=
"fol-KV-D65"
/>
<outlet
property=
"
mapButton"
destination=
"bTa-jT-Ufb"
id=
"gH0-yo-in7
"
/>
<outlet
property=
"
redeemButton"
destination=
"bTa-jT-Ufb"
id=
"zz9-GB-5CD
"
/>
<outlet
property=
"shareImage"
destination=
"a1t-wH-dMg"
id=
"Viw-KD-1JB"
/>
<outlet
property=
"subtitleLabel"
destination=
"iWC-mi-WKw"
id=
"peM-oa-eSS"
/>
<outlet
property=
"termsButton"
destination=
"eGV-3B-aQo"
id=
"Y0X-hP-SDU"
/>
...
...
@@ -28,7 +28,6 @@
<outlet
property=
"termsLabelHeight"
destination=
"9VB-9j-Q79"
id=
"G0C-tp-L7M"
/>
<outlet
property=
"titleLabel"
destination=
"aSO-pm-a0W"
id=
"uyw-AX-ElA"
/>
<outlet
property=
"view"
destination=
"i5M-Pr-FkT"
id=
"sfx-zR-JGt"
/>
<outlet
property=
"websiteButton"
destination=
"lU8-hR-MF0"
id=
"cj6-X8-D8Z"
/>
</connections>
</placeholder>
<placeholder
placeholderIdentifier=
"IBFirstResponder"
id=
"-2"
customClass=
"UIResponder"
/>
...
...
@@ -102,7 +101,7 @@
</constraints>
</imageView>
<label
opaque=
"NO"
userInteractionEnabled=
"NO"
contentMode=
"left"
horizontalHuggingPriority=
"251"
verticalHuggingPriority=
"251"
ambiguous=
"YES"
text=
"Label"
textAlignment=
"natural"
lineBreakMode=
"tailTruncation"
numberOfLines=
"0"
baselineAdjustment=
"alignBaselines"
adjustsFontSizeToFit=
"NO"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"iWC-mi-WKw"
userLabel=
"Subtitle Label"
>
<rect
key=
"frame"
x=
"24"
y=
"254.3333333333333
7"
width=
"345"
height=
"20.333333333333258
"
/>
<rect
key=
"frame"
x=
"24"
y=
"254.3333333333333
4"
width=
"345"
height=
"20.333333333333286
"
/>
<fontDescription
key=
"fontDescription"
type=
"system"
pointSize=
"17"
/>
<nil
key=
"textColor"
/>
<nil
key=
"highlightedColor"
/>
...
...
@@ -120,7 +119,7 @@
<nil
key=
"highlightedColor"
/>
</label>
<view
contentMode=
"scaleToFill"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"12M-YC-Cox"
userLabel=
"TermsButtonView"
>
<rect
key=
"frame"
x=
"23.999999999999993"
y=
"
452
.66666666666663"
width=
"123.33333333333331"
height=
"35"
/>
<rect
key=
"frame"
x=
"23.999999999999993"
y=
"
527
.66666666666663"
width=
"123.33333333333331"
height=
"35"
/>
<subviews>
<label
opaque=
"NO"
userInteractionEnabled=
"NO"
contentMode=
"left"
horizontalHuggingPriority=
"251"
verticalHuggingPriority=
"251"
text=
"Όροι Χρήσης"
textAlignment=
"natural"
lineBreakMode=
"tailTruncation"
baselineAdjustment=
"alignBaselines"
adjustsFontSizeToFit=
"NO"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"uSf-AS-iFa"
userLabel=
"TermsButtonTitleLabel"
>
<rect
key=
"frame"
x=
"0.0"
y=
"5"
width=
"101.33333333333333"
height=
"25"
/>
...
...
@@ -160,7 +159,7 @@
</constraints>
</view>
<label
opaque=
"NO"
userInteractionEnabled=
"NO"
contentMode=
"left"
horizontalHuggingPriority=
"251"
verticalHuggingPriority=
"251"
text=
"Label"
lineBreakMode=
"tailTruncation"
numberOfLines=
"0"
baselineAdjustment=
"alignBaselines"
adjustsFontSizeToFit=
"NO"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"jug-xV-lmv"
userLabel=
"TermsLabel"
>
<rect
key=
"frame"
x=
"24"
y=
"
497
.66666666666663"
width=
"345"
height=
"20.333333333333371"
/>
<rect
key=
"frame"
x=
"24"
y=
"
572
.66666666666663"
width=
"345"
height=
"20.333333333333371"
/>
<constraints>
<constraint
firstAttribute=
"height"
constant=
"20.329999999999998"
id=
"9VB-9j-Q79"
/>
</constraints>
...
...
@@ -168,18 +167,10 @@
<nil
key=
"textColor"
/>
<nil
key=
"highlightedColor"
/>
</label>
<button
opaque=
"NO"
contentMode=
"scaleToFill"
contentHorizontalAlignment=
"center"
contentVerticalAlignment=
"center"
buttonType=
"system"
lineBreakMode=
"middleTruncation"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"bTa-jT-Ufb"
userLabel=
"MapButton"
>
<rect
key=
"frame"
x=
"24"
y=
"558"
width=
"345"
height=
"55"
/>
<constraints>
<constraint
firstAttribute=
"height"
constant=
"55"
id=
"5AV-zY-O6v"
/>
</constraints>
<state
key=
"normal"
title=
"Button"
/>
<buttonConfiguration
key=
"configuration"
style=
"plain"
title=
"Button"
/>
</button>
<button
opaque=
"NO"
contentMode=
"scaleToFill"
contentHorizontalAlignment=
"center"
contentVerticalAlignment=
"center"
buttonType=
"system"
lineBreakMode=
"middleTruncation"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"lU8-hR-MF0"
userLabel=
"WebsiteButton"
>
<button
opaque=
"NO"
contentMode=
"scaleToFill"
contentHorizontalAlignment=
"center"
contentVerticalAlignment=
"center"
buttonType=
"system"
lineBreakMode=
"middleTruncation"
translatesAutoresizingMaskIntoConstraints=
"NO"
id=
"bTa-jT-Ufb"
userLabel=
"RedeemButton"
>
<rect
key=
"frame"
x=
"24"
y=
"633"
width=
"345"
height=
"55"
/>
<constraints>
<constraint
firstAttribute=
"height"
constant=
"55"
id=
"
aeV-F1-tWk
"
/>
<constraint
firstAttribute=
"height"
constant=
"55"
id=
"
5AV-zY-O6v
"
/>
</constraints>
<state
key=
"normal"
title=
"Button"
/>
<buttonConfiguration
key=
"configuration"
style=
"plain"
title=
"Button"
/>
...
...
@@ -192,7 +183,6 @@
<constraint
firstAttribute=
"trailing"
secondItem=
"50f-Uw-WmD"
secondAttribute=
"trailing"
id=
"5vF-D2-mBO"
/>
<constraint
firstItem=
"12M-YC-Cox"
firstAttribute=
"top"
secondItem=
"tOt-gP-Et5"
secondAttribute=
"bottom"
constant=
"50"
id=
"6cC-FH-1Xw"
/>
<constraint
firstItem=
"50f-Uw-WmD"
firstAttribute=
"leading"
secondItem=
"mci-HQ-9iu"
secondAttribute=
"leading"
id=
"7Rd-U6-d9j"
/>
<constraint
firstItem=
"lU8-hR-MF0"
firstAttribute=
"leading"
secondItem=
"mci-HQ-9iu"
secondAttribute=
"leading"
constant=
"24"
id=
"9R6-Lj-xSo"
/>
<constraint
firstItem=
"aSO-pm-a0W"
firstAttribute=
"leading"
secondItem=
"mci-HQ-9iu"
secondAttribute=
"leading"
constant=
"24"
id=
"BIn-gA-oSw"
/>
<constraint
firstItem=
"a1t-wH-dMg"
firstAttribute=
"leading"
secondItem=
"kQb-LM-Zaa"
secondAttribute=
"trailing"
constant=
"11"
id=
"DlZ-NN-vE2"
/>
<constraint
firstItem=
"12M-YC-Cox"
firstAttribute=
"leading"
secondItem=
"mci-HQ-9iu"
secondAttribute=
"leading"
constant=
"24"
id=
"Eal-pm-W9t"
/>
...
...
@@ -211,12 +201,10 @@
<constraint
firstItem=
"a1t-wH-dMg"
firstAttribute=
"top"
secondItem=
"50f-Uw-WmD"
secondAttribute=
"bottom"
constant=
"17"
id=
"bSw-JI-jDV"
/>
<constraint
firstItem=
"iWC-mi-WKw"
firstAttribute=
"leading"
secondItem=
"mci-HQ-9iu"
secondAttribute=
"leading"
constant=
"24"
id=
"dMq-cH-vOX"
/>
<constraint
firstItem=
"raJ-sJ-NGX"
firstAttribute=
"top"
secondItem=
"mci-HQ-9iu"
secondAttribute=
"top"
constant=
"17"
id=
"g7b-Ql-ifv"
/>
<constraint
firstItem=
"lU8-hR-MF0"
firstAttribute=
"top"
secondItem=
"bTa-jT-Ufb"
secondAttribute=
"bottom"
constant=
"20"
id=
"hGL-sc-uEw"
/>
<constraint
firstItem=
"aSO-pm-a0W"
firstAttribute=
"top"
secondItem=
"50f-Uw-WmD"
secondAttribute=
"bottom"
constant=
"23"
id=
"jvc-rb-E6b"
/>
<constraint
firstItem=
"tOt-gP-Et5"
firstAttribute=
"top"
secondItem=
"PZ8-Go-A85"
secondAttribute=
"bottom"
constant=
"20"
id=
"kQ3-4v-3Jp"
/>
<constraint
firstItem=
"jug-xV-lmv"
firstAttribute=
"top"
secondItem=
"12M-YC-Cox"
secondAttribute=
"bottom"
constant=
"9.9999999999998863"
id=
"kSx-qT-pPa"
/>
<constraint
firstAttribute=
"bottom"
secondItem=
"lU8-hR-MF0"
secondAttribute=
"bottom"
constant=
"46"
id=
"l1j-ca-Uq9"
/>
<constraint
firstAttribute=
"trailing"
secondItem=
"lU8-hR-MF0"
secondAttribute=
"trailing"
constant=
"24"
id=
"lEm-My-Oi9"
/>
<constraint
firstAttribute=
"bottom"
secondItem=
"bTa-jT-Ufb"
secondAttribute=
"bottom"
constant=
"46"
id=
"l42-O3-RQt"
/>
<constraint
firstItem=
"bTa-jT-Ufb"
firstAttribute=
"leading"
secondItem=
"mci-HQ-9iu"
secondAttribute=
"leading"
constant=
"24"
id=
"nR2-Py-LTi"
/>
<constraint
firstItem=
"jug-xV-lmv"
firstAttribute=
"leading"
secondItem=
"mci-HQ-9iu"
secondAttribute=
"leading"
constant=
"24"
id=
"oUa-cz-J7N"
/>
<constraint
firstItem=
"tOt-gP-Et5"
firstAttribute=
"leading"
secondItem=
"mci-HQ-9iu"
secondAttribute=
"leading"
constant=
"24"
id=
"xz5-C4-0GD"
/>
...
...
Please
register
or
login
to post a comment