Admin Workout Editor
Embedded view for creating and managing workouts and exercises. As users interact with the editor, your application will receive events that you can handle to trigger custom logic.
Available only for Flutter.
Custom Query Options:
| Option | Description |
| hidePlansTab | Hide the plans tab in the dashboard |
| tab | Default tab: "workouts", "exercises", or "plans" |
| isSelectableMenu | Show select button on cards, triggers `_selected` events |
Available Events:
*General Events:*
- `kinestex_loaded` - Application fully loaded
- `kinestex_launched` - Successful authentication
- `error_occurred` - Authentication error
*Exercise Events:*
- `exercise_opened` - Exercise detail page opened
- `exercise_selection_opened` - Exercise list page opened
- `exercise_selected` - Exercise selected from menu
- `exercise_saved` - Exercise created/updated
- `exercise_removed` - Exercise removed from workout
*Workout Events:*
- `workout_opened` - Workout detail page opened
- `workout_selection_opened` - Workout list page opened
- `workout_selected` - Workout selected from menu
- `workout_saved` - Workout created/updated
*Plan Events:*
- `plan_opened` - Plan detail page opened
- `plan_selection_opened` - Plan list page opened
- `plan_selected` - Plan selected from menu
- `plan_saved` - Plan created/updated
Admin Workout Editor Integration
Create the admin workout editor view for managing workouts and exercises:
1KinesteXAIFramework.createAdminWorkoutEditor(
2 // Use an organization name to differentiate between different orgs.
3 // If you don't plan to use multiple orgs, you can use your company name.
4 organization: "your_organization_name",
5 isShowKinestex: showKinesteX,
6 // OPTIONAL: show/hide content on the admin dashboard
7 customQueries: {
8 "hidePlansTab": true, // will hide the plans tabs in the dashboard
9 "tab": "workouts", // will default to workouts tab. Options: "exercises", "plans"
10 "isSelectableMenu": true // show select Button, triggers _selected events
11 },
12 isLoading: ValueNotifier<bool>(false),
13 onMessageReceived: (message) {
14 handleWebViewMessage(message);
15 },
16)Complete Example
Full implementation with event handling:
1import 'package:flutter/material.dart';
2import 'package:kinestex_sdk_flutter/kinestex_sdk.dart';
3import 'package:permission_handler/permission_handler.dart';
4
5Future<void> main() async {
6 WidgetsFlutterBinding.ensureInitialized();
7 await KinesteXAIFramework.initialize(
8 apiKey: "your_api_key",
9 companyName: "your_company_name",
10 userId: "your_user_id",
11 );
12 runApp(const MyApp());
13}
14
15class MyApp extends StatefulWidget {
16 const MyApp({super.key});
17
18
19 State<MyApp> createState() => _MyAppState();
20}
21
22class _MyAppState extends State<MyApp> {
23
24 void dispose() {
25 disposeKinesteXAIFramework();
26 super.dispose();
27 }
28
29 Future<void> disposeKinesteXAIFramework() async {
30 await KinesteXAIFramework.dispose();
31 }
32
33
34 Widget build(BuildContext context) {
35 return MaterialApp(
36 title: 'KinesteX Admin Editor',
37 theme: ThemeData(
38 primarySwatch: Colors.blue,
39 ),
40 home: const MyHomePage(),
41 );
42 }
43}
44
45class MyHomePage extends StatefulWidget {
46 const MyHomePage({super.key});
47
48
49 State<MyHomePage> createState() => _MyHomePageState();
50}
51
52class _MyHomePageState extends State<MyHomePage> {
53 ValueNotifier<bool> showKinesteX = ValueNotifier<bool>(false);
54
55
56 void initState() {
57 super.initState();
58 _checkCameraPermission();
59 }
60
61 void _checkCameraPermission() async {
62 if (await Permission.camera.request() != PermissionStatus.granted) {
63 _showCameraAccessDeniedAlert();
64 }
65 }
66
67 void _showCameraAccessDeniedAlert() {
68 showDialog(
69 context: context,
70 builder: (BuildContext context) {
71 return AlertDialog(
72 title: const Text("Camera Permission Denied"),
73 content: const Text("Camera access is required for this app to function properly."),
74 actions: <Widget>[
75 TextButton(
76 child: const Text("OK"),
77 onPressed: () => Navigator.of(context).pop(),
78 ),
79 ],
80 );
81 },
82 );
83 }
84
85 void handleWebViewMessage(WebViewMessage message) {
86 if (message is ExitKinestex) {
87 setState(() {
88 showKinesteX.value = false;
89 });
90 } else if (message is WorkoutSaved) {
91 print('Workout saved: ${message.data["workout_id"]}');
92 } else if (message is ExerciseSaved) {
93 print('Exercise saved: ${message.data["exercise_id"]}');
94 } else if (message is WorkoutSelected) {
95 print('Workout selected: ${message.data["workout_title"]}');
96 } else if (message is ExerciseSelected) {
97 print('Exercise selected: ${message.data["exercise_title"]}');
98 } else if (message is PlanSaved) {
99 print('Plan saved: ${message.data["plan_id"]}');
100 } else if (message is ErrorOccurred) {
101 print('Error: ${message.data["error_message"]}');
102 }
103 }
104
105 Widget createAdminWorkoutEditorView() {
106 return Center(
107 child: KinesteXAIFramework.createAdminWorkoutEditor(
108 organization: "your_organization_name",
109 isShowKinestex: showKinesteX,
110 customQueries: {
111 "hidePlansTab": false,
112 "tab": "workouts",
113 "isSelectableMenu": true,
114 },
115 isLoading: ValueNotifier<bool>(false),
116 onMessageReceived: handleWebViewMessage,
117 ),
118 );
119 }
120
121
122 Widget build(BuildContext context) {
123 return ValueListenableBuilder(
124 valueListenable: showKinesteX,
125 builder: (context, isShowKinesteX, child) {
126 return isShowKinesteX
127 ? SafeArea(
128 child: createAdminWorkoutEditorView(),
129 )
130 : Scaffold(
131 body: Center(
132 child: ElevatedButton(
133 style: ElevatedButton.styleFrom(
134 padding: const EdgeInsets.symmetric(
135 horizontal: 40,
136 vertical: 20,
137 ),
138 backgroundColor: Colors.green,
139 shape: RoundedRectangleBorder(
140 borderRadius: BorderRadius.circular(10),
141 ),
142 ),
143 onPressed: () {
144 showKinesteX.value = true;
145 },
146 child: const Text(
147 'Open Admin Workout Editor',
148 style: TextStyle(
149 fontSize: 20,
150 fontWeight: FontWeight.bold,
151 color: Colors.white,
152 ),
153 ),
154 ),
155 ),
156 );
157 },
158 );
159 }
160}Need Help?
Our team is ready to assist with your integration.

