커스텀창 - "체험하기"를 누르면 화면 전체 테마가 즉시 바뀌도록 수정
기존엔 미리보기가 큰 타일 하나만 바꾸고, 배경/카드 등 화면 전체는 실제 장착된 테마를 따로 불러와 보여줬다. 이제는 _resolvePreviewTemplate() 하나로 "지금 보여줄 테마"를 통일해서, 체험하기로 고른 템플릿이 배경색/ 보유 캐시 바/카드 전부에 즉시 반영된다. "기본 모습"을 고르면 화면 전체가 원래 모습으로 돌아간다. ShopTemplate에 code 필드를 추가해서 profileThemes 맵을 바로 찾아 쓸 수 있게 했다.
This commit is contained in:
@@ -9,6 +9,7 @@ import '../theme/profile_themes.dart';
|
|||||||
|
|
||||||
class ShopTemplate {
|
class ShopTemplate {
|
||||||
final int id;
|
final int id;
|
||||||
|
final String code;
|
||||||
final String category;
|
final String category;
|
||||||
final String name;
|
final String name;
|
||||||
final int price;
|
final int price;
|
||||||
@@ -19,6 +20,7 @@ class ShopTemplate {
|
|||||||
|
|
||||||
ShopTemplate({
|
ShopTemplate({
|
||||||
required this.id,
|
required this.id,
|
||||||
|
required this.code,
|
||||||
required this.category,
|
required this.category,
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.price,
|
required this.price,
|
||||||
@@ -31,6 +33,7 @@ class ShopTemplate {
|
|||||||
factory ShopTemplate.fromJson(Map<String, dynamic> json) {
|
factory ShopTemplate.fromJson(Map<String, dynamic> json) {
|
||||||
return ShopTemplate(
|
return ShopTemplate(
|
||||||
id: json['id'] as int,
|
id: json['id'] as int,
|
||||||
|
code: json['code'] as String,
|
||||||
category: json['category'] as String,
|
category: json['category'] as String,
|
||||||
name: json['name'] as String,
|
name: json['name'] as String,
|
||||||
price: json['price'] as int,
|
price: json['price'] as int,
|
||||||
|
|||||||
@@ -32,15 +32,10 @@ class _ProfileCustomizeScreenState extends State<ProfileCustomizeScreen> {
|
|||||||
// null = 아직 직접 고르지 않음(장착된 테마를 그대로 보여줌), -1 = "기본 모습"을 명시적으로 미리보는 중.
|
// null = 아직 직접 고르지 않음(장착된 테마를 그대로 보여줌), -1 = "기본 모습"을 명시적으로 미리보는 중.
|
||||||
int? _previewTemplateId;
|
int? _previewTemplateId;
|
||||||
|
|
||||||
// 🎨 지금 실제로 장착 중인 테마 - 화면 배경/상점 타일 자체를 이걸로 물들인다.
|
|
||||||
// (미리보기는 큰 타일 하나만 바뀌는 것과 별개로, 이건 "진짜 내 테마"를 화면 전체에 반영)
|
|
||||||
ProfileTheme? _equippedTheme;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_controller.loadCatalog(widget.studentId);
|
_controller.loadCatalog(widget.studentId);
|
||||||
_loadEquippedTheme();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -49,16 +44,8 @@ class _ProfileCustomizeScreenState extends State<ProfileCustomizeScreen> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadEquippedTheme() async {
|
/// 지금 큰 타일에 보여줄 템플릿을 고른다. 직접 미리보기를 누른 게 있으면 그걸,
|
||||||
final theme = await ProfileShopController.fetchEquippedTheme(
|
/// 없으면 실제 장착 중인 템플릿을, 그마저도 없으면 null(기본 모습)을 돌려준다.
|
||||||
widget.studentId,
|
|
||||||
);
|
|
||||||
if (!mounted) return;
|
|
||||||
setState(() => _equippedTheme = theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 지금 큰 타일에 보여줄 테마를 고른다. 직접 미리보기를 누른 게 있으면 그걸,
|
|
||||||
/// 없으면 실제 장착 중인 테마를, 그마저도 없으면 null(기본 모습)을 돌려준다.
|
|
||||||
ShopTemplate? _resolvePreviewTemplate() {
|
ShopTemplate? _resolvePreviewTemplate() {
|
||||||
if (_previewTemplateId == -1) return null;
|
if (_previewTemplateId == -1) return null;
|
||||||
if (_previewTemplateId != null) {
|
if (_previewTemplateId != null) {
|
||||||
@@ -72,6 +59,15 @@ class _ProfileCustomizeScreenState extends State<ProfileCustomizeScreen> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 🎨 지금 "체험하기/미리보기" 중인 테마로 화면 전체(배경/타일/버튼)를 물들인다.
|
||||||
|
/// 아무것도 직접 고르지 않았으면 실제 장착된 테마가 그대로 나오고, "기본 모습"을
|
||||||
|
/// 고르면 null이 되어 화면이 원래 모습으로 돌아간다 - 체험하기를 누르면 바로
|
||||||
|
/// 커스텀 화면 전체에 반영되는 효과를 _resolvePreviewTemplate() 하나로 처리한다.
|
||||||
|
ProfileTheme? get _displayTheme {
|
||||||
|
final preview = _resolvePreviewTemplate();
|
||||||
|
return preview == null ? null : profileThemes[preview.code];
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _handlePurchase(ShopTemplate template) async {
|
Future<void> _handlePurchase(ShopTemplate template) async {
|
||||||
setState(() => _previewTemplateId = template.id);
|
setState(() => _previewTemplateId = template.id);
|
||||||
final (success, message) = await _controller.purchase(
|
final (success, message) = await _controller.purchase(
|
||||||
@@ -92,7 +88,6 @@ class _ProfileCustomizeScreenState extends State<ProfileCustomizeScreen> {
|
|||||||
widget.studentId,
|
widget.studentId,
|
||||||
templateId,
|
templateId,
|
||||||
);
|
);
|
||||||
if (success) await _loadEquippedTheme();
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
AppNotice.show(
|
AppNotice.show(
|
||||||
context,
|
context,
|
||||||
@@ -104,7 +99,7 @@ class _ProfileCustomizeScreenState extends State<ProfileCustomizeScreen> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: _equippedTheme?.background ?? AppPalette.mist,
|
backgroundColor: _displayTheme?.background ?? AppPalette.mist,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
foregroundColor: AppPalette.ink,
|
foregroundColor: AppPalette.ink,
|
||||||
@@ -148,7 +143,7 @@ class _ProfileCustomizeScreenState extends State<ProfileCustomizeScreen> {
|
|||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14),
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: _equippedTheme?.secondary ?? AppPalette.ink,
|
color: _displayTheme?.secondary ?? AppPalette.ink,
|
||||||
borderRadius: BorderRadius.circular(18),
|
borderRadius: BorderRadius.circular(18),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -246,7 +241,7 @@ class _ProfileCustomizeScreenState extends State<ProfileCustomizeScreen> {
|
|||||||
_DefaultTemplateTile(
|
_DefaultTemplateTile(
|
||||||
equipped: !hasEquippedTemplate,
|
equipped: !hasEquippedTemplate,
|
||||||
previewing: previewId == null,
|
previewing: previewId == null,
|
||||||
theme: _equippedTheme,
|
theme: _displayTheme,
|
||||||
onEquip: () => _handleEquip(null),
|
onEquip: () => _handleEquip(null),
|
||||||
onPreview: () => setState(() => _previewTemplateId = -1),
|
onPreview: () => setState(() => _previewTemplateId = -1),
|
||||||
),
|
),
|
||||||
@@ -255,7 +250,7 @@ class _ProfileCustomizeScreenState extends State<ProfileCustomizeScreen> {
|
|||||||
template: template,
|
template: template,
|
||||||
canAfford: _controller.cashBalance >= template.price,
|
canAfford: _controller.cashBalance >= template.price,
|
||||||
previewing: previewId == template.id,
|
previewing: previewId == template.id,
|
||||||
theme: _equippedTheme,
|
theme: _displayTheme,
|
||||||
onPurchase: () => _handlePurchase(template),
|
onPurchase: () => _handlePurchase(template),
|
||||||
onEquip: () => _handleEquip(template.id),
|
onEquip: () => _handleEquip(template.id),
|
||||||
onPreview: () => setState(() => _previewTemplateId = template.id),
|
onPreview: () => setState(() => _previewTemplateId = template.id),
|
||||||
|
|||||||
Reference in New Issue
Block a user