diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 66228370f1eddb0d5503f135e467a40925c108bb..7d85bfccd13014544c189fefc0c9deef6d58d3c0 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -15,15 +15,13 @@ PODS:
     - Flutter
   - package_info_plus (0.4.5):
     - Flutter
-  - path_provider_foundation (0.0.1):
+  - path_provider_ios (0.0.1):
     - Flutter
-    - FlutterMacOS
   - permission_handler_apple (9.0.4):
     - Flutter
   - ReachabilitySwift (5.0.0)
-  - shared_preferences_foundation (0.0.1):
+  - shared_preferences_ios (0.0.1):
     - Flutter
-    - FlutterMacOS
   - sqflite (0.0.2):
     - Flutter
     - FMDB (>= 2.7.5)
@@ -46,9 +44,9 @@ DEPENDENCIES:
   - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
   - open_filex (from `.symlinks/plugins/open_filex/ios`)
   - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
-  - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
+  - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
   - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
-  - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
+  - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
   - sqflite (from `.symlinks/plugins/sqflite/ios`)
   - updater (from `.symlinks/plugins/updater/ios`)
   - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
@@ -75,12 +73,12 @@ EXTERNAL SOURCES:
     :path: ".symlinks/plugins/open_filex/ios"
   package_info_plus:
     :path: ".symlinks/plugins/package_info_plus/ios"
-  path_provider_foundation:
-    :path: ".symlinks/plugins/path_provider_foundation/ios"
+  path_provider_ios:
+    :path: ".symlinks/plugins/path_provider_ios/ios"
   permission_handler_apple:
     :path: ".symlinks/plugins/permission_handler_apple/ios"
-  shared_preferences_foundation:
-    :path: ".symlinks/plugins/shared_preferences_foundation/ios"
+  shared_preferences_ios:
+    :path: ".symlinks/plugins/shared_preferences_ios/ios"
   sqflite:
     :path: ".symlinks/plugins/sqflite/ios"
   updater:
@@ -102,14 +100,14 @@ SPEC CHECKSUMS:
   image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb
   open_filex: 6e26e659846ec990262224a12ef1c528bb4edbe4
   package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
-  path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
+  path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
   permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
   ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
-  shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca
+  shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
   sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
   Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
   updater: d6c70e66a13a3704329f41f5653dd6e503753fa5
-  url_launcher_ios: fb12c43172927bb5cf75aeebd073f883801f1993
+  url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
   video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
   wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
   webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f
diff --git a/lib/core/widgets/input_field_with_title.dart b/lib/core/widgets/input_field_with_title.dart
index 6a1d2d3f338efd6264a3d992e463b4c2842497be..734b3ed50041d0851133d7d9492830659534b1ca 100644
--- a/lib/core/widgets/input_field_with_title.dart
+++ b/lib/core/widgets/input_field_with_title.dart
@@ -5,8 +5,9 @@ class InputFieldWithTitle extends StatefulWidget {
   final String placeHolder;
   final TextEditingController controller;
   final int? maxLines;
+  final ValueChanged<String>? onChanged;
 
-  const InputFieldWithTitle({required this.title, required this.placeHolder, required this.controller, this.maxLines = 1, Key? key}) : super(key: key);
+  const InputFieldWithTitle({required this.title, required this.placeHolder, required this.controller, this.maxLines = 1, this.onChanged, Key? key}) : super(key: key);
 
   @override
   State<StatefulWidget> createState() => _InputFieldWithTitleState();
@@ -31,6 +32,7 @@ class _InputFieldWithTitleState extends State<InputFieldWithTitle> {
               style: const TextStyle(color: Color(0xFF03162F), fontSize: 14, fontWeight: FontWeight.w400),
               maxLines: widget.maxLines,
               cursorColor: const Color(0xFFFC6D26),
+              onChanged: widget.onChanged,
               decoration: InputDecoration(
                   hintText: widget.placeHolder,
                   hintStyle: const TextStyle(fontSize: 14),
diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb
index b63c7f0a6ac71f51928f47030cc2fade8ada3d48..d76f5a985a05c3a8a158ba6fd4852b83c7fa4cd8 100644
--- a/lib/l10n/intl_en.arb
+++ b/lib/l10n/intl_en.arb
@@ -252,5 +252,6 @@
   "in_discussions_and_create_posts": "in discussions and create posts",
   "other_connection_not_allow": "Other connect methods are only support to view",
   "to_connect": "To Connect",
-  "post": "Post"
+  "post": "Post",
+  "faqType": "Type (required)"
 }
diff --git a/lib/l10n/intl_zh.arb b/lib/l10n/intl_zh.arb
index db3eed9ca2a48efae26b7116dfa2e250cc969537..6c7119b14f4c63e4b7a3a654b03e7b5c665186d5 100644
--- a/lib/l10n/intl_zh.arb
+++ b/lib/l10n/intl_zh.arb
@@ -252,5 +252,7 @@
   "in_discussions_and_create_posts": "或创建帖子",
   "other_connection_not_allow": "其他连接方式仅支持浏览",
   "to_connect": "连接",
-  "post": "帖子"
+  "post": "帖子",
+  "faqType": "版块(必填)"
+
 }
diff --git a/lib/modules/faq/faq_creation_model.dart b/lib/modules/faq/faq_creation_model.dart
index 120a7fbad40edab7c1e691010de77232f70d5cc2..ba24f8fb782f6a0cc37bbe63847f835f4d87dc5c 100644
--- a/lib/modules/faq/faq_creation_model.dart
+++ b/lib/modules/faq/faq_creation_model.dart
@@ -1,5 +1,10 @@
+import 'dart:async';
+
+import 'package:flutter/cupertino.dart';
 import 'package:jihu_gitlab_app/core/net/http_client.dart';
 import 'package:jihu_gitlab_app/core/user_provider/user_provider.dart';
+import 'package:jihu_gitlab_app/modules/faq/faq_model.dart';
+import 'package:jihu_gitlab_app/modules/faq/faq_type_repo.dart';
 import 'package:jihu_gitlab_app/modules/issues/manage/models/issue_draft_entity.dart';
 import 'package:jihu_gitlab_app/modules/issues/manage/models/issue_draft_repository.dart';
 
@@ -8,28 +13,37 @@ import '../../core/net/api.dart';
 class FaqCreationModel {
   late int _projectId;
   final IssueDraftRepository _repository = IssueDraftRepository();
+  final List<FaqType> _faqTypes = [];
+  late ValueNotifier<List<FaqType>> _notifier;
+  FaqType? _selectedFaqType;
+  String? _title;
 
   void init(int projectId) {
     _projectId = projectId;
+    _notifier = ValueNotifier(_faqTypes);
+    FaqTypeRepo.instance().getFaqTypes().then((faqTypes) {
+      _faqTypes.addAll(faqTypes);
+      _notifier.value = List.of(_faqTypes);
+    });
   }
 
-  Future<bool> create(int projectId, String title, {String? description, String? labels}) async {
+  Future<bool> create(int projectId, String title, Locale locale, {String? description, String? labels}) async {
     try {
       String uri = Api().jihu().join('/projects/$projectId/issues');
       var body = <String, dynamic>{'title': title};
       if (description != null) {
         body['description'] = description;
       }
+      body['labels'] = [_selectedFaqType!.name, locale == const Locale("zh") ? "lang::zh" : "lang::en"].join(",");
       await HttpClient.instance().postWithHeader<Map<String, dynamic>>(uri, body, ConnectionProvider().jiHuConnection!.authHeaders);
       _repository.delete(projectId, ConnectionProvider().jiHuConnection!.userInfo.id);
+      _reset();
       return Future.value(true);
     } catch (error) {
       return Future.value(false);
     }
   }
 
-  int get projectId => _projectId;
-
   void saveAsDraft(String title, String description) async {
     var userId = ConnectionProvider().jiHuConnection!.userInfo.id;
     var faqDraft = {
@@ -51,4 +65,25 @@ class FaqCreationModel {
     List<IssueDraftEntity> issueDrafts = await _repository.query(projectId, ConnectionProvider().jiHuConnection!.userInfo.id);
     return issueDrafts;
   }
+
+  void selectFaqType(FaqType faqType) {
+    _selectedFaqType = faqType;
+  }
+
+  bool isSelected(FaqType faqType) {
+    return _selectedFaqType == faqType;
+  }
+
+  void _reset() {
+    _selectedFaqType = null;
+    _title = null;
+  }
+
+  void changeTitle(String text) => _title = text;
+
+  int get projectId => _projectId;
+
+  ValueNotifier<List<FaqType>> get notifier => _notifier;
+
+  bool get submittable => _selectedFaqType != null && _title != null && _title!.isNotEmpty;
 }
diff --git a/lib/modules/faq/faq_creation_page.dart b/lib/modules/faq/faq_creation_page.dart
index 8dc2b7eea678425930220b5e7d2484a5b7321e67..7c809d07a6e8aab3ac42396fc7ed8f44f13abf9b 100644
--- a/lib/modules/faq/faq_creation_page.dart
+++ b/lib/modules/faq/faq_creation_page.dart
@@ -7,9 +7,11 @@ import 'package:jihu_gitlab_app/core/widgets/common_app_bar.dart';
 import 'package:jihu_gitlab_app/core/widgets/connect_jihu_page.dart';
 import 'package:jihu_gitlab_app/core/widgets/input_field_with_title.dart';
 import 'package:jihu_gitlab_app/core/widgets/markdown/markdown_input_box.dart';
+import 'package:jihu_gitlab_app/core/widgets/streaming_container.dart';
 import 'package:jihu_gitlab_app/core/widgets/toast.dart';
 import 'package:jihu_gitlab_app/l10n/jihu_localizations.dart';
 import 'package:jihu_gitlab_app/modules/faq/faq_creation_model.dart';
+import 'package:jihu_gitlab_app/modules/faq/faq_model.dart';
 import 'package:provider/provider.dart';
 
 class FaqCreationPage extends StatefulWidget {
@@ -71,21 +73,23 @@ class _FaqCreationPageState extends State<FaqCreationPage> {
                 Container(
                   transform: Matrix4.translationValues(-12, 2, 0),
                   child: TextButton(
-                      onPressed: () {
-                        var title = _issueTitleController.text;
-                        var description = _issueDescriptionController.text;
-                        Loader.showProgress(context);
-                        _model.create(widget.arguments['projectId'], title, description: description).then((value) {
-                          Loader.hideProgress(context);
-                          if (value) {
-                            Toast.success(context, JiHuLocalizations.dictionary().createSuccessful);
-                            Navigator.pop(context, true);
-                          } else {
-                            Toast.error(context, JiHuLocalizations.dictionary().createFailed);
-                          }
-                        });
-                      },
-                      child: Text(JiHuLocalizations.dictionary().create, style: TextStyle(color: Theme.of(context).primaryColor))),
+                      onPressed: _model.submittable
+                          ? () {
+                              var title = _issueTitleController.text;
+                              var description = _issueDescriptionController.text;
+                              Loader.showProgress(context);
+                              _model.create(widget.arguments['projectId'], title, description: description, Localizations.localeOf(context)).then((value) {
+                                Loader.hideProgress(context);
+                                if (value) {
+                                  Toast.success(context, JiHuLocalizations.dictionary().createSuccessful);
+                                  Navigator.pop(context, true);
+                                } else {
+                                  Toast.error(context, JiHuLocalizations.dictionary().createFailed);
+                                }
+                              });
+                            }
+                          : null,
+                      child: Text(JiHuLocalizations.dictionary().create, style: TextStyle(color: Theme.of(context).primaryColor.withOpacity(_model.submittable ? 1 : 0.5)))),
                 ),
               ],
             ),
@@ -94,9 +98,16 @@ class _FaqCreationPageState extends State<FaqCreationPage> {
                 child: SafeArea(
                   child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
                     InputFieldWithTitle(
-                        title: JiHuLocalizations.dictionary().createIssueTitle,
-                        placeHolder: JiHuLocalizations.dictionary().issueTitlePlaceholder(JiHuLocalizations.dictionary().post),
-                        controller: _issueTitleController),
+                      title: JiHuLocalizations.dictionary().createIssueTitle,
+                      placeHolder: JiHuLocalizations.dictionary().issueTitlePlaceholder(JiHuLocalizations.dictionary().post),
+                      controller: _issueTitleController,
+                      onChanged: (text) {
+                        _model.changeTitle(text);
+                        setState(() {});
+                      },
+                    ),
+                    _buildTitle(JiHuLocalizations.dictionary().faqType),
+                    _buildFaqTypeSelector(),
                     _buildTitle(JiHuLocalizations.dictionary().description),
                     Container(
                         margin: const EdgeInsets.symmetric(horizontal: 16),
@@ -129,4 +140,32 @@ class _FaqCreationPageState extends State<FaqCreationPage> {
       setState(() {});
     }
   }
+
+  Widget _buildFaqTypeSelector() {
+    return Padding(
+      padding: const EdgeInsets.symmetric(horizontal: 16),
+      child: ValueListenableBuilder<List<FaqType>>(
+        valueListenable: _model.notifier,
+        builder: (context, data, child) => StreamingContainer(children: data.map((e) => _buildFaqTypeRadio(e)).toList()),
+      ),
+    );
+  }
+
+  Widget _buildFaqTypeRadio(FaqType faqType) {
+    return InkWell(
+      onTap: () => setState(() => _model.selectFaqType(faqType)),
+      child: Stack(
+        children: [
+          Container(
+            padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
+            decoration: BoxDecoration(color: _model.isSelected(faqType) ? const Color(0xFFFFEBE2) : Colors.white, borderRadius: const BorderRadius.all(Radius.circular(4))),
+            child: Text(
+              faqType.typeName(Localizations.localeOf(context)),
+              style: TextStyle(color: Color(_model.isSelected(faqType) ? 0xFFFC6D26 : 0xFF03162F), fontSize: 13, fontWeight: FontWeight.w400),
+            ),
+          )
+        ],
+      ),
+    );
+  }
 }
diff --git a/lib/modules/faq/faq_model.dart b/lib/modules/faq/faq_model.dart
index a3cf139f496df7fc7f912729b4ab6a730c21128a..9325ff6e7f77609613d8269daf9dd12c50ea3305 100644
--- a/lib/modules/faq/faq_model.dart
+++ b/lib/modules/faq/faq_model.dart
@@ -2,7 +2,9 @@ import 'package:flutter/material.dart';
 import 'package:jihu_gitlab_app/core/id.dart';
 import 'package:jihu_gitlab_app/core/net/api.dart';
 import 'package:jihu_gitlab_app/core/net/http_client.dart';
+import 'package:jihu_gitlab_app/core/user_provider/user_provider.dart';
 import 'package:jihu_gitlab_app/modules/faq/faq.dart';
+import 'package:jihu_gitlab_app/modules/faq/faq_type_repo.dart';
 import 'package:jihu_gitlab_app/modules/issues/manage/widgets/label.dart';
 
 class FaqType extends Label {
@@ -28,7 +30,6 @@ class FaqType extends Label {
 class FaqModel {
   static const int _faqProjectId = 89335;
   static const String _faqRelativePath = 'ultimate-plan/jihu-gitlab-app/faq';
-  static const String _faqTypePrefix = 'type';
   late ValueNotifier<List<FaqType>> _notifier;
   final List<FaqType> _faqTypes = [FaqType.all];
   late TabController _tabController;
@@ -37,35 +38,19 @@ class FaqModel {
   Future<void> init(TickerProvider tickerProvider) {
     _notifier = ValueNotifier(_faqTypes);
     _tabController = TabController(length: _faqTypes.length, vsync: tickerProvider);
-    return _getFaqTypes().then((value) {
+    return FaqTypeRepo.instance().getFaqTypes().then((value) {
       _faqTypes.addAll(value);
       _tabController = TabController(length: _faqTypes.length, vsync: tickerProvider);
       _notifier.value = List.of(_faqTypes);
     });
   }
 
-  Future<List<FaqType>> _getFaqTypes() async {
-    var response = await HttpClient.instance().post(Api().jihu().graphQL(), {
-      "query": """
-     {
-        project(fullPath:"$_faqRelativePath"){
-          labels{
-            nodes{
-              id
-              title
-              description
-            }
-          }
-        }
-      } 
-    """
+  Future<bool> checkUserIsProjectMember() {
+    if (ConnectionProvider().jiHuConnection == null) return Future.value(false);
+    return HttpClient.instance().get(Api().jihu().join("projects/$_faqProjectId")).then((response) {
+      int? accessLevel = response.body()["permissions"]?['project_access']?['access_level'];
+      return Future(() => accessLevel != null && accessLevel > 0);
     });
-    return ((response.body()['data']?['project']?['labels']?['nodes'] ?? []) as List)
-        .map((e) => FaqType.fromGraphqlJson(e))
-        .where((e) => e.name.isNotEmpty)
-        .where((e) => e.name.startsWith(_faqTypePrefix))
-        .toSet()
-        .toList();
   }
 
   void changeSelectedFaq(Faq? faq) {
diff --git a/lib/modules/faq/faq_page.dart b/lib/modules/faq/faq_page.dart
index 908806a69e2e39a4885f025f093bdc26aace369c..c82cd6386f28833d9334b154fa7cbaca3a979d51 100644
--- a/lib/modules/faq/faq_page.dart
+++ b/lib/modules/faq/faq_page.dart
@@ -58,16 +58,28 @@ class _FaqPageState extends State<FaqPage> with TickerProviderStateMixin {
   Widget _buildListPage() {
     return HomeScaffold.withAppBar(
       params: HomeAppBarRequiredParams(title: Text(JiHuLocalizations.dictionary().community), context: context, actions: [
-        IconButton(
-          icon: const Icon(Icons.add_box_outlined),
-          color: const Color(0xFF87878C),
-          onPressed: () async {
-            Navigator.of(context).pushNamed(FaqCreationPage.routeName, arguments: {"projectId": _model.projectId}).then((value) {
-              if (value != null && value is bool && value == true) {
-                _refreshKey.currentState?.onRefresh();
-                setState(() {});
-              }
-            });
+        Consumer<ConnectionProvider>(
+          builder: (context, _, child) {
+            return FutureBuilder<bool>(
+              initialData: false,
+              future: _model.checkUserIsProjectMember(),
+              builder: (context, snapshot) {
+                return (snapshot.data ?? false)
+                    ? IconButton(
+                        icon: const Icon(Icons.add_box_outlined),
+                        color: const Color(0xFF87878C),
+                        onPressed: () async {
+                          Navigator.of(context).pushNamed(FaqCreationPage.routeName, arguments: {"projectId": _model.projectId}).then((value) {
+                            if (value != null && value is bool && value == true) {
+                              _refreshKey.currentState?.onRefresh();
+                              setState(() {});
+                            }
+                          });
+                        },
+                      )
+                    : const SizedBox();
+              },
+            );
           },
         )
       ]),
diff --git a/lib/modules/faq/faq_type_repo.dart b/lib/modules/faq/faq_type_repo.dart
new file mode 100644
index 0000000000000000000000000000000000000000..fa03f3b1599f53f02332ebef69442157542ec0ae
--- /dev/null
+++ b/lib/modules/faq/faq_type_repo.dart
@@ -0,0 +1,38 @@
+import 'package:jihu_gitlab_app/core/net/api.dart';
+import 'package:jihu_gitlab_app/core/net/http_client.dart';
+import 'package:jihu_gitlab_app/modules/faq/faq_model.dart';
+
+class FaqTypeRepo {
+  static const String _faqRelativePath = 'ultimate-plan/jihu-gitlab-app/faq';
+  static const String _faqTypePrefix = 'type';
+
+  static final FaqTypeRepo _instance = FaqTypeRepo._internal();
+
+  FaqTypeRepo._internal();
+
+  factory FaqTypeRepo.instance() => _instance;
+
+  Future<List<FaqType>> getFaqTypes() async {
+    var response = await HttpClient.instance().post(Api().jihu().graphQL(), {
+      "query": """
+     {
+        project(fullPath:"$_faqRelativePath"){
+          labels{
+            nodes{
+              id
+              title
+              description
+            }
+          }
+        }
+      } 
+    """
+    });
+    return ((response.body()['data']?['project']?['labels']?['nodes'] ?? []) as List)
+        .map((e) => FaqType.fromGraphqlJson(e))
+        .where((e) => e.name.isNotEmpty)
+        .where((e) => e.name.startsWith(_faqTypePrefix))
+        .toSet()
+        .toList();
+  }
+}
diff --git a/lib/modules/issues/manage/models/issue_draft_entity.dart b/lib/modules/issues/manage/models/issue_draft_entity.dart
index d6279e8f609e05788c62bccd1aeb9de374ca20e0..a8b6bdc1020e9542b8f18d28fd482637662c840d 100644
--- a/lib/modules/issues/manage/models/issue_draft_entity.dart
+++ b/lib/modules/issues/manage/models/issue_draft_entity.dart
@@ -19,8 +19,8 @@ class IssueDraftEntity {
   IssueDraftEntity._internal(this.userId, this.projectId, this.title, this.description, this.template, this.assignees, this.labels, this.confidential, this.version);
 
   static IssueDraftEntity restore(Map<String, dynamic> map) {
-    List<Member> members = !map.containsKey('selected_assignees') ? [] : (jsonDecode(map['selected_assignees']) as List).map((e) => Member.fromJson(e)).toList();
-    List<Label> labels = !map.containsKey('selected_labels') ? [] : (jsonDecode(map['selected_labels']) as List).map((e) => Label.fromJson(e)).toList();
+    List<Member> members = !map.containsKey('selected_assignees') ? [] : ((jsonDecode(map['selected_assignees']) ?? []) as List).map((e) => Member.fromJson(e)).toList();
+    List<Label> labels = !map.containsKey('selected_labels') ? [] : ((jsonDecode(map['selected_labels']) ?? []) as List).map((e) => Label.fromJson(e)).toList();
     return IssueDraftEntity._internal(map['user_id'], map['project_id'], map['title'], map['description'], map['template'], members, labels, map['confidential'] ?? 0, map['version']);
   }
 
diff --git a/test/integration_tests/create_faq_test.dart b/test/integration_tests/create_faq_test.dart
index efaec318aae7ea73537209b6850ce5c3be9d32e4..c3d894f283b4d8feef53e9ce19edc83dd59b5a34 100644
--- a/test/integration_tests/create_faq_test.dart
+++ b/test/integration_tests/create_faq_test.dart
@@ -6,7 +6,7 @@ import 'package:jihu_gitlab_app/core/local_storage.dart';
 import 'package:jihu_gitlab_app/core/net/http_client.dart';
 import 'package:jihu_gitlab_app/core/net/response.dart' as r;
 import 'package:jihu_gitlab_app/core/user_provider/user_provider.dart';
-import 'package:jihu_gitlab_app/core/widgets/connect_jihu_page.dart';
+import 'package:jihu_gitlab_app/core/widgets/streaming_container.dart';
 import 'package:jihu_gitlab_app/generated/l10n.dart';
 import 'package:jihu_gitlab_app/l10n/current_locale.dart';
 import 'package:jihu_gitlab_app/modules/faq/faq_creation_page.dart';
@@ -34,12 +34,17 @@ void main() {
     ConnectionProvider().reset(Tester.jihuLabUser());
     ConnectionProvider().injectConnectionForTest(Tester.selfManagedUser());
     client = MockHttpClient();
+    when(client.get("https://jihulab.com/api/v4/projects/89335")).thenAnswer((_) => Future(() => r.Response.of({
+          "permissions": {
+            "project_access": {"access_level": 50}
+          }
+        })));
     HttpClient.injectInstanceForTesting(client);
   });
 
   testWidgets('Should create faq', (WidgetTester tester) async {
     setUpMobileBinding(tester);
-    when(client.post('https://jihulab.com/api/graphql', any)).thenAnswer((_) => Future(() => r.Response.of(faqListResponse)));
+    when(client.post('https://jihulab.com/api/graphql', argThat(predicate((arg) => arg.toString().contains("labels"))))).thenAnswer((_) => Future(() => r.Response.of(faqTypesResponse)));
     when(client.postWithHeader<Map<String, dynamic>>('https://jihulab.com/api/v4/projects/89335/issues', any, any)).thenAnswer((_) => Future(() => r.Response.of<Map<String, dynamic>>({})));
     HttpClient.injectInstanceForTesting(client);
 
@@ -58,6 +63,8 @@ void main() {
     await tester.pumpAndSettle();
     expect(find.byType(FaqCreationPage), findsOneWidget);
     expect(find.text("Title (required)"), findsOneWidget);
+    expect(find.text("Type (required)"), findsOneWidget);
+    expect(find.byType(StreamingContainer), findsOneWidget);
     expect(find.text("Write a Post title"), findsOneWidget);
     expect(find.text("Description"), findsOneWidget);
     expect(find.text("Write a description here..."), findsOneWidget);
@@ -65,11 +72,20 @@ void main() {
     expect(SvgFinder("assets/images/photo_picker.svg"), findsOneWidget);
     expect(SvgFinder("assets/images/numbers.svg"), findsNothing);
     expect(SvgFinder("assets/images/alternate_email.svg"), findsNothing);
+    expect(find.text("FAQ"), findsOneWidget);
+    expect(find.text("WFH"), findsOneWidget);
+    var buttonFinder = find.widgetWithText(TextButton, "Create");
+    expect(buttonFinder, findsOneWidget);
+    expect(tester.firstWidget<TextButton>(buttonFinder).onPressed, null);
+
     await tester.enterText(find.byWidgetPredicate((widget) => widget is TextField && widget.decoration?.hintText == 'Write a Post title'), 'example');
     await tester.pumpAndSettle();
     await tester.enterText(find.byWidgetPredicate((widget) => widget is TextField && widget.decoration?.hintText == 'Write a description here...'), 'example');
     await tester.pumpAndSettle();
-    await tester.tap(find.byType(TextButton));
+    await tester.tap(find.text("FAQ"));
+    await tester.pumpAndSettle();
+    expect(tester.firstWidget<TextButton>(buttonFinder).onPressed, predicate((value) => value != null));
+    await tester.tap(buttonFinder);
     await tester.pumpAndSettle(const Duration(seconds: 2));
     expect(find.byType(FaqPage), findsOneWidget);
   });
@@ -132,7 +148,7 @@ void main() {
     await tester.tap(find.byIcon(Icons.add_box_outlined));
   });
 
-  testWidgets('Should see to connect page when no login account', (WidgetTester tester) async {
+  testWidgets('Should not see the connect page when no login account', (WidgetTester tester) async {
     setUpMobileBinding(tester);
     ConnectionProvider().loggedOut(true);
     ConnectionProvider().clearActive();
@@ -150,29 +166,33 @@ void main() {
     ));
 
     await tester.pumpAndSettle(const Duration(seconds: 1));
-    expect(find.byIcon(Icons.add_box_outlined), findsOneWidget);
-    await tester.tap(find.byIcon(Icons.add_box_outlined));
-    await tester.pumpAndSettle();
-    expect(find.byType(ConnectJihuPage), findsOneWidget);
-    expect(find.textContaining("Connect with jihulab.com to participate"), findsOneWidget);
-    await tester.tap(find.text("To Connect"));
-    await tester.pumpAndSettle();
-    ConnectionProvider().reset(Tester.jihuLabUser());
-    await tester.tap(find.byType(BackButton));
-    await tester.pumpAndSettle();
-    expect(find.byType(FaqCreationPage), findsOneWidget);
-    expect(find.text("Title (required)"), findsOneWidget);
-    expect(find.text("Write a Post title"), findsOneWidget);
-    expect(find.text("Description"), findsOneWidget);
-    expect(find.text("Write a description here..."), findsOneWidget);
-    expect(SvgFinder("assets/images/video_picker.svg"), findsOneWidget);
-    expect(SvgFinder("assets/images/photo_picker.svg"), findsOneWidget);
-    expect(SvgFinder("assets/images/numbers.svg"), findsNothing);
-    expect(SvgFinder("assets/images/alternate_email.svg"), findsNothing);
+    expect(find.byIcon(Icons.add_box_outlined), findsNothing);
+  });
+
+  testWidgets('Should not see the connect page when user is not the project member', (WidgetTester tester) async {
+    setUpMobileBinding(tester);
+    when(client.post('https://jihulab.com/api/graphql', any)).thenAnswer((_) => Future(() => r.Response.of(faqListResponse)));
+    when(client.get("https://jihulab.com/api/v4/projects/89335")).thenAnswer((_) => Future(() => r.Response.of({
+          "permissions": {"project_access": null}
+        })));
+    HttpClient.injectInstanceForTesting(client);
+
+    await tester.pumpWidget(MultiProvider(
+      providers: [ChangeNotifierProvider(create: (context) => ConnectionProvider()), ChangeNotifierProvider(create: (context) => LocaleProvider())],
+      child: MaterialApp(
+        onGenerateRoute: onGenerateRoute,
+        home: const Scaffold(body: FaqPage()),
+        localizationsDelegates: const [GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, GlobalWidgetsLocalizations.delegate, S.delegate],
+      ),
+    ));
+
+    await tester.pumpAndSettle(const Duration(seconds: 1));
+    expect(find.byIcon(Icons.add_box_outlined), findsNothing);
   });
 
   tearDown(() {
     ConnectionProvider().fullReset();
+    reset(client);
   });
 }
 
@@ -190,3 +210,24 @@ Map<String, dynamic> faqListResponse = {
     }
   }
 };
+
+Map<String, dynamic> faqTypesResponse = {
+  "data": {
+    "project": {
+      "labels": {
+        "nodes": [
+          {
+            "id": "gid://gitlab/ProjectLabel/72395",
+            "title": "type::FAQ",
+            "description": "问答",
+          },
+          {
+            "id": "gid://gitlab/ProjectLabel/72059",
+            "title": "type::WFH",
+            "description": "远程办公",
+          },
+        ]
+      }
+    }
+  }
+};
diff --git a/test/integration_tests/modules/merge_request/launch_app_and_reopen_merge_request_test.dart b/test/integration_tests/modules/merge_request/launch_app_and_reopen_merge_request_test.dart
index 11da6176fe9b758ccf18ad922bb2dc2b60c87617..562c38c4c685c9f7ac27b90d95592cdf942e0a10 100644
--- a/test/integration_tests/modules/merge_request/launch_app_and_reopen_merge_request_test.dart
+++ b/test/integration_tests/modules/merge_request/launch_app_and_reopen_merge_request_test.dart
@@ -38,6 +38,11 @@ void main() {
     when(client.get<List<dynamic>>("/api/v4/todos?page=1&per_page=20&state=pending")).thenAnswer((_) => Future(() => Response.of<List<dynamic>>(todoPendingResponseData)));
     when(client.get<List<dynamic>>("/api/v4/projects/72936/issues/6/discussions?page=1&per_page=50")).thenAnswer((_) => Future(() => Response.of<List<dynamic>>(discussionsData)));
     when(client.get<List<dynamic>>("/api/v4/projects/72936/labels")).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([])));
+    when(client.get("https://jihulab.com/api/v4/projects/89335")).thenAnswer((_) => Future(() => Response.of({
+          "permissions": {
+            "project_access": {"access_level": 50}
+          }
+        })));
     HttpClient.injectInstanceForTesting(client);
   });
 
diff --git a/test/integration_tests/modules/projects/projects_page_test.dart b/test/integration_tests/modules/projects/projects_page_test.dart
index 3fc1b96d4cd92f3f7bab25b7799372682d8989ef..8432e047141f1edfd3ac64b9ea015a5765c92719 100644
--- a/test/integration_tests/modules/projects/projects_page_test.dart
+++ b/test/integration_tests/modules/projects/projects_page_test.dart
@@ -61,6 +61,11 @@ void main() {
     when(client.get("/api/v4/users/9527/starred_projects?page=1&per_page=50")).thenAnswer((realInvocation) => Future(() => Response.of([])));
     when(client.get<List<dynamic>>("/api/v4/todos?page=1&per_page=20&state=pending")).thenAnswer((realInvocation) => Future(() => Response.of<List<dynamic>>(todoPendingResponseData)));
     when(client.get<List<dynamic>>("/api/v4/groups?top_level_only=true&page=1&per_page=50")).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([])));
+    when(client.get("https://jihulab.com/api/v4/projects/89335")).thenAnswer((_) => Future(() => Response.of({
+          "permissions": {
+            "project_access": {"access_level": 50}
+          }
+        })));
     HttpClient.injectInstanceForTesting(client);
   });
 
diff --git a/test/integration_tests/modules/to_dos/to_dos_page_test.dart b/test/integration_tests/modules/to_dos/to_dos_page_test.dart
index 1dbed0a70d6eec0f593ac3cc0c7c20232a1a060a..50639853d4efa63a12bb9aaea3a8b2120dc93d21 100644
--- a/test/integration_tests/modules/to_dos/to_dos_page_test.dart
+++ b/test/integration_tests/modules/to_dos/to_dos_page_test.dart
@@ -42,6 +42,11 @@ void main() {
     when(client.get<List<dynamic>>("/api/v4/todos?page=1&per_page=20&state=pending")).thenAnswer((_) => Future(() => Response.of<List<dynamic>>(todoPendingResponseData)));
     when(client.get<List<dynamic>>("/api/v4/projects/72936/issues/6/discussions?page=1&per_page=50")).thenAnswer((_) => Future(() => Response.of<List<dynamic>>(discussionsData)));
     when(client.get<List<dynamic>>("/api/v4/projects/72936/labels")).thenAnswer((_) => Future(() => Response.of<List<dynamic>>([])));
+    when(client.get("https://jihulab.com/api/v4/projects/89335")).thenAnswer((_) => Future(() => Response.of({
+          "permissions": {
+            "project_access": {"access_level": 50}
+          }
+        })));
     HttpClient.injectInstanceForTesting(client);
   });
 
diff --git a/test/modules/faq/faq_page_test.dart b/test/modules/faq/faq_page_test.dart
index 4a80dbe1f71f898c72fabc8ac94474db9abfd81d..5060f6047edf082ec6fb8774af7ba79ca592d1fb 100644
--- a/test/modules/faq/faq_page_test.dart
+++ b/test/modules/faq/faq_page_test.dart
@@ -48,6 +48,11 @@ void main() {
         .thenAnswer((_) => Future(() => r.Response.of<Map<String, dynamic>>({})));
     when(client.getWithHeader<Map<String, dynamic>>("https://jihulab.com/api/v4/projects/89335", {"PRIVATE-TOKEN": '', "authorization": ''}))
         .thenAnswer((_) => Future(() => r.Response.of<Map<String, dynamic>>({})));
+    when(client.get("https://jihulab.com/api/v4/projects/89335")).thenAnswer((_) => Future(() => r.Response.of({
+          "permissions": {
+            "project_access": {"access_level": 50}
+          }
+        })));
     HttpClient.injectInstanceForTesting(client);
 
     await tester.pumpWidget(MultiProvider(