Skip to content

Commit 125dcbc

Browse files
authored
[Horizon] Updating Attempts Allowed String for Singular Case (#3351)
1 parent c113aa8 commit 125dcbc

File tree

7 files changed

+220
-294
lines changed

7 files changed

+220
-294
lines changed

Horizon/Horizon/Resources/Localizable.xcstrings

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,32 @@
2020
}
2121
}
2222
},
23+
"%@ Attempts Allowed" : {
24+
"comment" : "The number of attempts allowed for this assignment."
25+
},
26+
"%lld Attempts Allowed" : {
27+
"comment" : "The number of attempts allowed for this assignment.",
28+
"localizations" : {
29+
"en" : {
30+
"variations" : {
31+
"plural" : {
32+
"one" : {
33+
"stringUnit" : {
34+
"state" : "translated",
35+
"value" : "%lld Attempt Allowed"
36+
}
37+
},
38+
"other" : {
39+
"stringUnit" : {
40+
"state" : "new",
41+
"value" : "%lld Attempts Allowed"
42+
}
43+
}
44+
}
45+
}
46+
}
47+
}
48+
},
2349
"Abu Dhabi (+04:00/+04:00)" : {
2450

2551
},
@@ -265,6 +291,9 @@
265291
},
266292
"Dublin (+01:00/+00:00)" : {
267293

294+
},
295+
"Due" : {
296+
268297
},
269298
"Due Date" : {
270299

@@ -631,6 +660,9 @@
631660
},
632661
"Osaka (+09:00)" : {
633662

663+
},
664+
"Overdue" : {
665+
634666
},
635667
"Overview" : {
636668

@@ -657,6 +689,9 @@
657689
},
658690
"Philippines (+08:00)" : {
659691

692+
},
693+
"Points Possible" : {
694+
660695
},
661696
"Port Moresby (+10:00/+10:00)" : {
662697

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
//
2+
// This file is part of Canvas.
3+
// Copyright (C) 2025-present Instructure, Inc.
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as
7+
// published by the Free Software Foundation, either version 3 of the
8+
// License, or (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
//
18+
19+
import HorizonUI
20+
import SwiftUI
21+
22+
struct IntroBlock: View {
23+
// MARK: - Dependencies
24+
25+
let moduleName: String
26+
let moduleItemName: String
27+
let duration: String?
28+
let countOfPoints: String?
29+
let dueDate: String?
30+
let isOverdue: Bool
31+
let attemptCount: String?
32+
let backgroundColor: Color
33+
let foregroundColor: Color
34+
let isMenuButtonVisible: Bool
35+
let onBack: () -> Void
36+
let onMenu: () -> Void
37+
38+
// MARK: - Init
39+
40+
public init(
41+
moduleName: String,
42+
moduleItemName: String,
43+
duration: String?,
44+
countOfPoints: String? = nil,
45+
dueDate: String?,
46+
isOverdue: Bool = false,
47+
attemptCount: String? = nil,
48+
backgroundColor: Color = Color.huiColors.surface.institution,
49+
foregroundColor: Color = Color.huiColors.text.surfaceColored,
50+
isMenuButtonVisible: Bool = true,
51+
onBack: @escaping () -> Void,
52+
onMenu: @escaping () -> Void
53+
) {
54+
self.moduleName = moduleName
55+
self.moduleItemName = moduleItemName
56+
self.duration = duration
57+
self.countOfPoints = countOfPoints
58+
self.dueDate = dueDate
59+
self.isOverdue = isOverdue
60+
self.attemptCount = attemptCount
61+
self.backgroundColor = backgroundColor
62+
self.foregroundColor = foregroundColor
63+
self.isMenuButtonVisible = isMenuButtonVisible
64+
self.onBack = onBack
65+
self.onMenu = onMenu
66+
}
67+
68+
public var body: some View {
69+
VStack(spacing: .huiSpaces.space12) {
70+
HStack {
71+
backButton
72+
Spacer()
73+
moduleTitleView
74+
Spacer()
75+
menuButton
76+
}
77+
moduleInfoView
78+
if let attemptsAllowed = attemptsAllowed {
79+
Text(attemptsAllowed)
80+
.huiTypography(.p2)
81+
.foregroundStyle(foregroundColor)
82+
}
83+
if isOverdue {
84+
HorizonUI.Pill(
85+
title: String(localized: "Overdue", bundle: .horizon),
86+
style: .outline(.init(borderColor: foregroundColor, textColor: foregroundColor, iconColor: foregroundColor)),
87+
isUppercased: true,
88+
icon: nil
89+
)
90+
}
91+
}
92+
.padding(.horizontal, .huiSpaces.space24)
93+
.padding(.bottom, .huiSpaces.space24)
94+
.background {
95+
Rectangle()
96+
.fill(backgroundColor)
97+
}
98+
}
99+
100+
private var moduleTitleView: some View {
101+
VStack(spacing: .huiSpaces.space4) {
102+
Text(moduleName)
103+
.huiTypography(.p3)
104+
.lineLimit(1)
105+
106+
Text(moduleItemName)
107+
.huiTypography(.labelLargeBold)
108+
.lineLimit(2)
109+
}
110+
.foregroundColor(foregroundColor)
111+
.multilineTextAlignment(.center)
112+
}
113+
114+
private var backButton: some View {
115+
Button(action: onBack) {
116+
Image.huiIcons.arrowLeftAlt
117+
.foregroundColor(foregroundColor)
118+
}
119+
.frame(width: .huiSpaces.space24, height: .huiSpaces.space24)
120+
}
121+
122+
@ViewBuilder
123+
private var menuButton: some View {
124+
if isMenuButtonVisible {
125+
Button(action: onMenu) {
126+
Image.huiIcons.listAlt
127+
.foregroundColor(foregroundColor)
128+
}
129+
.frame(width: .huiSpaces.space24, height: .huiSpaces.space24)
130+
}
131+
}
132+
133+
private var moduleInfoView: some View {
134+
Text(moduleItemInfo)
135+
.foregroundStyle(foregroundColor)
136+
.huiTypography(.p2)
137+
.padding(.horizontal, .huiSpaces.space16)
138+
}
139+
140+
private var moduleItemInfo: String {
141+
let dueText = dueDate.map { "\(String(localized: "Due", bundle: .horizon)) \($0)" }
142+
let pointsText = countOfPoints.map { "\($0) \(String(localized: "Points Possible", bundle: .horizon))" }
143+
let items = [duration, dueText, pointsText].compactMap { $0 }
144+
return items.joined(separator: items.count == 1 ? "" : " | ")
145+
}
146+
147+
private var attemptsAllowed: String? {
148+
guard let attemptCount = attemptCount else {
149+
return nil
150+
}
151+
152+
if let attempts = Int(attemptCount) {
153+
return String(
154+
localized: "\(attempts) Attempts Allowed",
155+
comment: "The number of attempts allowed for this assignment."
156+
)
157+
}
158+
159+
return String(
160+
localized: "\(attemptCount) Attempts Allowed",
161+
comment: "The number of attempts allowed for this assignment."
162+
)
163+
}
164+
}
165+
166+
#Preview {
167+
IntroBlock(
168+
moduleName: "Module Name Amet Adipiscing Elit",
169+
moduleItemName: "Learning Object Name Lorem Ipsum Dolor Learning Object Name Lorem Ipsum Dolor",
170+
duration: "XX Mins",
171+
countOfPoints: "10",
172+
dueDate: "Due 10/12",
173+
isOverdue: true,
174+
attemptCount: "Three",
175+
onBack: {},
176+
onMenu: {}
177+
)
178+
}

Horizon/Horizon/Sources/Features/ModuleItemSequence/Sequence/View/ModuleItemSequenceView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public struct ModuleItemSequenceView: View {
134134
@ViewBuilder
135135
private var introBlock: some View {
136136
if isShowHeader {
137-
HorizonUI.IntroBlock(
137+
IntroBlock(
138138
moduleName: viewModel.moduleItem?.moduleName ?? "",
139139
moduleItemName: viewModel.moduleItem?.title ?? "",
140140
duration: viewModel.estimatedTime,

packages/HorizonUI/Sources/HorizonUI/Sources/Components/IntroBlock/HorizonUI.IntroBlock.Storybook.swift

Lines changed: 0 additions & 126 deletions
This file was deleted.

0 commit comments

Comments
 (0)