Skip to content

Instantly share code, notes, and snippets.

@AlejandroCalzadilla
Created June 10, 2025 12:24
Show Gist options
  • Save AlejandroCalzadilla/db6be2d20dcb3f0979d8f234eecd06f7 to your computer and use it in GitHub Desktop.
Save AlejandroCalzadilla/db6be2d20dcb3f0979d8f234eecd06f7 to your computer and use it in GitHub Desktop.
Código Flutter generado desde la pizarra
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'dart:math'; // Required for `pi` and `Transform.rotate`
class Componentdtyumj0s extends StatelessWidget {
const Componentdtyumj0s({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
// The body's background color is derived from the main content container #if44n
backgroundColor: const Color(0xFFE9E9F4),
body: Stack(
// Stack is used to place the main scrollable content and the fixed footer.
children: [
SingleChildScrollView(
// SingleChildScrollView prevents vertical overflow for long content.
child: Column(
// This Column corresponds to the #if44n div, acting as the main content wrapper.
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center, // align-items:center
children: [
// Top section including time and Hello Bettan card - corresponds to #iaht9
Container(
width: double.infinity, // width:100%
color: const Color(0xFFE9E9F4), // background-color:#E9E9F4
padding: const EdgeInsets.all(20), // padding:20px
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, // For centering inner elements
children: [
// Time display section - corresponds to #i31xs
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400), // max-width:400px
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // justify-content:space-between
children: const [
Text(
'9:30', // #if7x8
style: TextStyle(
fontSize: 16,
color: Color(0xFF212121),
),
),
SizedBox
.shrink(), // Placeholder for the empty div in HTML, has no effect
],
),
),
const SizedBox(height: 20), // margin-top equivalent spacing
// Hello Bettan profile card - corresponds to #ihwdg
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFE9E9F4), // background-color:#E9E9F4
borderRadius: BorderRadius.circular(24), // border-radius:24px
),
padding: const EdgeInsets.all(20), // padding:20px
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // justify-content:space-between
crossAxisAlignment: CrossAxisAlignment.center, // align-items:center
children: [
// Purple circular image/gradient container - #ityfj
Container(
width: 140, // width:140px
height: 140, // height:140px
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(70), // border-radius:50% for circle
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFFBA68C8), // From linear-gradient
Color(0xFF9575CD),
],
),
),
child: ClipOval(
// ClipOval ensures the inner transformed element stays within the circle.
child: Transform.translate(
offset: const Offset(-10, -20), // translate(-10px, -20px)
child: Transform.rotate(
angle: -20 * (pi / 180), // rotate(-20deg)
child: Opacity(
opacity: 0.2, // opacity:0.2
child: Container(
// Inner element for the gradient effect - #i3qzl
width: 140,
height: 140,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFFBA68C8),
Color(0xFF9575CD),
],
),
),
),
),
),
),
),
),
const SizedBox(width: 20), // Spacing between circle and text
// Text content for the card - corresponds to #istdf
Expanded(
// Expanded ensures text takes available space and handles overflow.
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start, // align-items:flex-start
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
'Hello, Bettan!', // #ikbg6
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Color(0xFF212121),
),
maxLines: 1, // white-space:nowrap, overflow:hidden
overflow: TextOverflow.ellipsis, // text-overflow:ellipsis
),
Text(
'Ready for new knowledge?', // #ienk5
style: TextStyle(
fontSize: 14,
color: Color(0xFF757575),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
),
),
const SizedBox(height: 20),
// "Continue course" button - corresponds to #i14fg
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: ElevatedButton(
onPressed: () {
// TODO: Add button functionality here
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF3F51B5), // background-color:#3F51B5
foregroundColor: Colors.white, // text color
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), // border-radius:12px
),
minimumSize: const Size(
double.infinity, 48), // width:100%, height:48px
padding:
EdgeInsets.zero, // Remove default padding to allow inner Row to control.
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.string(
// SVG for play icon - #ivero
'''
<svg viewBox="0 0 24 24" fill="currentColor" id="ivero"><path d="M8 5v14l11-7z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg>
''',
width: 24, // width:24px
height: 24, // height:24px
colorFilter: const ColorFilter.mode(
Colors.white, BlendMode.srcIn), // fill:currentColor, which is white
),
const SizedBox(width: 8), // margin-right:8px
const Text(
'Continue course',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
const SizedBox(height: 20),
// Favourite Courses / Lectures section - corresponds to #iyckp
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, // justify-content:space-around
children: [
// Favourite Courses card - corresponds to #i04ul
Expanded(
// Expanded ensures cards take equal space and handles min-width
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFEDE7F6), // background-color:#EDE7F6
borderRadius: BorderRadius.circular(16), // border-radius:16px
),
padding: const EdgeInsets.symmetric(
vertical: 15, horizontal: 20), // padding:15px 20px
margin: const EdgeInsets.symmetric(
horizontal: 5), // Added margin to space out
child: Column(
children: [
Container(
width: 44, // width:44px
height: 44, // height:44px
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(22), // border-radius:50%
color: const Color(0xFFD1C4E9), // background-color:#D1C4E9
),
alignment: Alignment.center,
child: SvgPicture.string(
// SVG for heart icon - #iqgk2
'''
<svg viewBox="0 0 24 24" id="iqgk2"><path d="M0 0h24v24H0z" fill="none"></path><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"></path></svg>
''',
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(
Color(0xFF9575CD), BlendMode.srcIn), // color:#9575CD
),
),
const SizedBox(height: 5), // margin-bottom:5px
const Text(
'Favourite Courses', // #igxr6
style: TextStyle(
fontSize: 14,
color: Color(0xFF212121),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
),
// Favourite Lectures card - corresponds to #i9unk
Expanded(
// Expanded ensures cards take equal space
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFEDE7F6),
borderRadius: BorderRadius.circular(16),
),
padding: const EdgeInsets.symmetric(
vertical: 15, horizontal: 20),
margin: const EdgeInsets.symmetric(
horizontal: 5), // Added margin to space out
child: Column(
children: [
Container(
width: 44,
height: 44,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(22),
color: const Color(0xFFD1C4E9),
),
alignment: Alignment.center,
child: SvgPicture.string(
// SVG for heart icon - #i6ifr
'''
<svg viewBox="0 0 24 24" id="i6ifr"><path d="M0 0h24v24H0z" fill="none"></path><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"></path></svg>
''',
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(
Color(0xFF9575CD), BlendMode.srcIn),
),
),
const SizedBox(height: 5),
const Text(
'Favourite Lectures', // #ivwdi
style: TextStyle(
fontSize: 14,
color: Color(0xFF212121),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
),
],
),
),
const SizedBox(height: 20),
// Mastering Copywriting card - corresponds to #iaypu
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFEDE7F6), // background-color:#EDE7F6
borderRadius: BorderRadius.circular(20), // border-radius:20px
),
padding: const EdgeInsets.all(20), // padding:20px
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
// Circular image/gradient container - #iulq9
Container(
width: 60, // width:60px
height: 60, // height:60px
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30), // border-radius:50%
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFFBA68C8),
Color(0xFF9575CD),
],
),
),
child: ClipOval(
child: Transform.translate(
offset: const Offset(-5, -10), // translate(-5px, -10px)
child: Transform.rotate(
angle: -20 * (pi / 180), // rotate(-20deg)
child: Opacity(
opacity: 0.1, // opacity:0.1
child: Container(
// Inner element for gradient effect - #iza42
width: 60,
height: 60,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFFBA68C8),
Color(0xFF9575CD),
],
),
),
),
),
),
),
),
),
const SizedBox(width: 10), // margin-right:10px
// Text content for the course - #i0ogh
Expanded(
// Expanded ensures text takes available width.
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Marketing', // #ifi42
style: TextStyle(
fontSize: 12,
color: Color(0xFF757575),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Text(
'Mastering Copywriting', // #ix4rf
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Color(0xFF212121),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
const SizedBox(height: 10), // margin-top:10px
// Progress bar - corresponds to #izu2v
Container(
height: 8, // height:8px
width: double
.infinity, // width:100% of its constrained parent
decoration: BoxDecoration(
color: const Color(0xFFD1C4E9), // background-color:#D1C4E9
borderRadius: BorderRadius.circular(4), // border-radius:4px
),
child: Align(
alignment: Alignment.centerLeft,
child: FractionallySizedBox(
// FractionallySizedBox for width:20%
widthFactor: 0.2,
child: Container(
height: 8,
decoration: BoxDecoration(
color: const Color(0xFF9575CD), // background-color:#9575CD
borderRadius: BorderRadius.circular(4),
),
),
),
),
),
],
),
),
),
const SizedBox(height: 20),
// Recommended Courses header - corresponds to #i6emp
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10), // padding:0 10px
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // justify-content:space-between
crossAxisAlignment: CrossAxisAlignment.center, // align-items:center
children: [
const Expanded(
// Expanded allows the text to fill space and ellipsis
child: Text(
'Recommended Courses', // #i9pit
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Color(0xFF212121),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
SvgPicture.string(
// SVG for arrow icon - #iwz3r
'''
<svg viewBox="0 0 24 24" id="iwz3r"><path d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg>
''',
width: 24, // width:24px
height: 24, // height:24px
colorFilter: const ColorFilter.mode(
Color(0xFF757575), BlendMode.srcIn), // color:#757575
),
],
),
),
),
const SizedBox(height: 10),
// Budgeting Strategies card - corresponds to #i2eq1
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFEDE7F6), // background-color:#EDE7F6
borderRadius: BorderRadius.circular(20), // border-radius:20px
),
padding: const EdgeInsets.all(20), // padding:20px
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // justify-content:space-between
crossAxisAlignment: CrossAxisAlignment.center, // align-items:center
children: [
Row(
children: [
// Circular image/gradient container - #ilo3j
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFFBA68C8),
Color(0xFF9575CD),
],
),
),
child: ClipOval(
child: Transform.translate(
offset: const Offset(-5, -10),
child: Transform.rotate(
angle: -20 * (pi / 180),
child: Opacity(
opacity: 0.1,
child: Container(
// Inner element for gradient effect - #i8otx
width: 60,
height: 60,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFFBA68C8),
Color(0xFF9575CD),
],
),
),
),
),
),
),
),
),
const SizedBox(width: 10),
// Text content for the course - #i865r
Expanded(
// Expanded for text in Row
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Marketing', // #i8us7
style: TextStyle(
fontSize: 12,
color: Color(0xFF757575),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Text(
'Budgeting Strategies', // #i2b7m
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Color(0xFF212121),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
// Heart button - #ix7fl
ElevatedButton(
onPressed: () {
// TODO: Add button functionality here
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white, // background-color:#FFFFFF
shape: const CircleBorder(), // border-radius:50%
padding: EdgeInsets.zero,
minimumSize: const Size(44, 44), // width:44px, height:44px
),
child: SvgPicture.string(
// SVG for heart icon - #iyemg
'''
<svg viewBox="0 0 24 24" id="iyemg"><path d="M0 0h24v24H0z" fill="none"></path><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"></path></svg>
''',
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(
Color(0xFF9575CD), BlendMode.srcIn), // color:#9575CD
),
),
],
),
const SizedBox(height: 10),
// Rating and views section - #ielup
Row(
children: [
SvgPicture.string(
// SVG for star icon - #i2sh2
'''
<svg viewBox="0 0 24 24" id="i2sh2"><path d="M0 0h24v24H0z" fill="none"></path><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path></svg>
''',
width: 16,
height: 16,
colorFilter: const ColorFilter.mode(
Color(0xFF757575), BlendMode.srcIn), // color:#757575
),
const SizedBox(width: 5),
const Text(
'5', // #ifj16
style: TextStyle(
fontSize: 14,
color: Color(0xFF757575),
),
),
const SizedBox(width: 10),
SvgPicture.string(
// SVG for eye icon - #if8np
'''
<svg viewBox="0 0 24 24" id="if8np"><path d="M0 0h24v24H0z" fill="none"></path><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zm0 13c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm0-11.5c-2.49 0-4.5 2.01-4.5 4.5s2.01 4.5 4.5 4.5 4.5-2.01 4.5-4.5-2.01-4.5-4.5-4.5z"></path></svg>
''',
width: 16,
height: 16,
colorFilter: const ColorFilter.mode(
Color(0xFF757575), BlendMode.srcIn), // color:#757575
),
const SizedBox(width: 5),
const Text(
'12', // #im7l6
style: TextStyle(
fontSize: 14,
color: Color(0xFF757575),
),
),
],
),
],
),
),
),
],
),
),
// Adds padding at the bottom of the scrollable content to prevent it from being obscured by the fixed footer.
const SizedBox(height: 80),
],
),
),
// Fixed bottom navigation bar - corresponds to #izodz
Positioned(
bottom: 0, // position:fixed, bottom:0
left: 0, // left:0
right: 0, // Spans full width
child: Container(
height: 60, // height:60px
decoration: const BoxDecoration(
color: Colors.white, // background-color:#FFFFFF
border: Border(
top: BorderSide(
color: Color(0xFFE0E0E0),
width: 1), // border-top:1px solid #E0E0E0
),
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround, // justify-content:space-around
children: [
// Home icon and text - #izsmp
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.string(
// SVG for home icon - #idjx8
'''
<svg viewBox="0 0 24 24" id="idjx8"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 21h3v-8h4v8z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg>
''',
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(
Color(0xFF757575), BlendMode.srcIn), // color:#757575
),
const Text(
'Home', // #izvnn
style: TextStyle(
fontSize: 12,
color: Color(0xFF757575),
),
),
],
),
// Catalog icon and text - #ivuvv7
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.string(
// SVG for catalog icon - #ildl0r
'''
<svg viewBox="0 0 24 24" id="ildl0r"><path d="M0 0h24v24H0z" fill="none"></path><path d="M20.87 20.17l-5.59-5.59C15.91 13.18 17 11.06 17 8.5 17 5.46 14.54 3 11.5 3S6 5.46 6 8.5c0 2.56 1.09 4.68 2.97 6.08l-5.59 5.59c-.78.78-.78 2.05 0 2.83L4.54 21.68c.78.78 2.05.78 2.83 0l5.59-5.59C11.06 15.91 13.18 15 15.7 15 18.74 15 21 17.46 21 20.5c0 .59-.1 1.16-.29 1.72l1.59 1.59c.78.78 2.05.78 2.83 0l1.41-1.41c.78-.78.78-2.05 0-2.83zM11.5 7c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2z"></path></svg>
''',
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(
Color(0xFF757575), BlendMode.srcIn),
),
const Text(
'Catalog', // #i3ftrl
style: TextStyle(
fontSize: 12,
color: Color(0xFF757575),
),
),
],
),
// Notes icon and text - #i2rr88
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.string(
// SVG for notes icon - #iv9cjn
'''
<svg viewBox="0 0 24 24" id="iv9cjn"><path d="M0 0h24v24H0z" fill="none"></path><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm5 17H7v-2h12v2zm0-4H7v-2h12v2zm0-4H7V7h12v2z"></path></svg>
''',
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(
Color(0xFF757575), BlendMode.srcIn),
),
const Text(
'Notes', // #ii2qyi
style: TextStyle(
fontSize: 12,
color: Color(0xFF757575),
),
),
],
),
// Profile icon and text - #i9bm29
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.string(
// SVG for profile icon - #iqqimd
'''
<svg viewBox="0 0 24 24" id="iqqimd"><path d="M0 0h24v24H0z" fill="none"></path><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"></path></svg>
''',
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(
Color(0xFF757575), BlendMode.srcIn),
),
const Text(
'Profile', // #imwdju
style: TextStyle(
fontSize: 12,
color: Color(0xFF757575),
),
),
],
),
],
),
),
),
],
),
);
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Navigation Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Navigation Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Componentdtyumj0s()),
);
},
child: const Text('Go to Componentdtyumj0s'),
),
const SizedBox(height: 20),
],
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment